aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorVassil Vassilev <v.g.vassilev@gmail.com>2021-03-17 08:56:05 +0000
committerVassil Vassilev <v.g.vassilev@gmail.com>2021-03-17 08:59:04 +0000
commit0cb7e7ca0c864e052bf49978f3bcd667c9e16930 (patch)
treee379b22e8130e19c619d5101e00ae7c475fd7915 /clang/lib/Sema
parent3b8b5d1f22f2c5d8ae55709a92d02011dea056ca (diff)
downloadllvm-0cb7e7ca0c864e052bf49978f3bcd667c9e16930.zip
llvm-0cb7e7ca0c864e052bf49978f3bcd667c9e16930.tar.gz
llvm-0cb7e7ca0c864e052bf49978f3bcd667c9e16930.tar.bz2
Make iteration over the DeclContext::lookup_result safe.
The idiom: ``` DeclContext::lookup_result R = DeclContext::lookup(Name); for (auto *D : R) {...} ``` is not safe when in the loop body we trigger deserialization from an AST file. The deserialization can insert new declarations in the StoredDeclsList whose underlying type is a vector. When the vector decides to reallocate its storage the pointer we hold becomes invalid. This patch replaces a SmallVector with an singly-linked list. The current approach stores a SmallVector<NamedDecl*, 4> which is around 8 pointers. The linked list is 3, 5, or 7. We do better in terms of memory usage for small cases (and worse in terms of locality -- the linked list entries won't be near each other, but will be near their corresponding declarations, and we were going to fetch those memory pages anyway). For larger cases: the vector uses a doubling strategy for reallocation, so will generally be between half-full and full. Let's say it's 75% full on average, so there's N * 4/3 + 4 pointers' worth of space allocated currently and will be 2N pointers with the linked list. So we break even when there are N=6 entries and slightly lose in terms of memory usage after that. We suspect that's still a win on average. Thanks to @rsmith! Differential revision: https://reviews.llvm.org/D91524
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp1
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp16
-rw-r--r--clang/lib/Sema/SemaLookup.cpp33
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp40
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp3
5 files changed, 41 insertions, 52 deletions
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 252008c..3a993e2 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/MultiplexExternalSemaSource.h"
-#include "clang/AST/DeclContextInternals.h"
#include "clang/Sema/Lookup.h"
using namespace clang;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 0365d77..10f61d8 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4130,13 +4130,9 @@ ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
IdentifierInfo *MemberOrBase) {
if (SS.getScopeRep() || TemplateTypeTy)
return nullptr;
- DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
- if (Result.empty())
- return nullptr;
- ValueDecl *Member;
- if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
- (Member = dyn_cast<IndirectFieldDecl>(Result.front())))
- return Member;
+ for (auto *D : ClassDecl->lookup(MemberOrBase))
+ if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
+ return cast<ValueDecl>(D);
return nullptr;
}
@@ -9672,9 +9668,9 @@ public:
bool foundSameNameMethod = false;
SmallVector<CXXMethodDecl *, 8> overloadedMethods;
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
+ for (Path.Decls = BaseRecord->lookup(Name).begin();
+ Path.Decls != DeclContext::lookup_iterator(); ++Path.Decls) {
+ NamedDecl *D = *Path.Decls;
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
MD = MD->getCanonicalDecl();
foundSameNameMethod = true;
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index b6bf882..fef96b2 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -638,8 +638,8 @@ void LookupResult::resolveKind() {
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
CXXBasePaths::const_paths_iterator I, E;
for (I = P.begin(), E = P.end(); I != E; ++I)
- for (DeclContext::lookup_iterator DI = I->Decls.begin(),
- DE = I->Decls.end(); DI != DE; ++DI)
+ for (DeclContext::lookup_iterator DI = I->Decls, DE = DI.end(); DI != DE;
+ ++DI)
addDecl(*DI);
}
@@ -2230,9 +2230,9 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl();
// Drop leading non-matching lookup results from the declaration list so
// we don't need to consider them again below.
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- if (Path.Decls.front()->isInIdentifierNamespace(IDNS))
+ for (Path.Decls = BaseRecord->lookup(Name).begin();
+ Path.Decls != Path.Decls.end(); ++Path.Decls) {
+ if ((*Path.Decls)->isInIdentifierNamespace(IDNS))
return true;
}
return false;
@@ -2256,9 +2256,9 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
AccessSpecifier SubobjectAccess = AS_none;
// Check whether the given lookup result contains only static members.
- auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) {
- for (NamedDecl *ND : Result)
- if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember())
+ auto HasOnlyStaticMembers = [&](DeclContext::lookup_iterator Result) {
+ for (DeclContext::lookup_iterator I = Result, E = I.end(); I != E; ++I)
+ if ((*I)->isInIdentifierNamespace(IDNS) && (*I)->isCXXInstanceMember())
return false;
return true;
};
@@ -2267,8 +2267,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Determine whether two sets of members contain the same members, as
// required by C++ [class.member.lookup]p6.
- auto HasSameDeclarations = [&](DeclContextLookupResult A,
- DeclContextLookupResult B) {
+ auto HasSameDeclarations = [&](DeclContext::lookup_iterator A,
+ DeclContext::lookup_iterator B) {
using Iterator = DeclContextLookupResult::iterator;
using Result = const void *;
@@ -2305,7 +2305,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// We'll often find the declarations are in the same order. Handle this
// case (and the special case of only one declaration) efficiently.
- Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end();
+ Iterator AIt = A, BIt = B, AEnd, BEnd;
while (true) {
Result AResult = Next(AIt, AEnd);
Result BResult = Next(BIt, BEnd);
@@ -2388,10 +2388,11 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Lookup in a base class succeeded; return these results.
- for (auto *D : Paths.front().Decls) {
+ for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
+ I != E; ++I) {
AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
- D->getAccess());
- if (NamedDecl *ND = R.getAcceptableDecl(D))
+ (*I)->getAccess());
+ if (NamedDecl *ND = R.getAcceptableDecl(*I))
R.addDecl(ND, AS);
}
R.resolveKind();
@@ -2534,7 +2535,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
<< Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
<< LookupRange;
- DeclContext::lookup_iterator Found = Paths->front().Decls.begin();
+ DeclContext::lookup_iterator Found = Paths->front().Decls;
while (isa<CXXMethodDecl>(*Found) &&
cast<CXXMethodDecl>(*Found)->isStatic())
++Found;
@@ -2552,7 +2553,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
for (CXXBasePaths::paths_iterator Path = Paths->begin(),
PathEnd = Paths->end();
Path != PathEnd; ++Path) {
- const NamedDecl *D = Path->Decls.front();
+ const NamedDecl *D = *Path->Decls;
if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace()))
continue;
if (DeclsPrinted.insert(D).second) {
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index fdc30fe..db99927 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -112,12 +112,10 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
return;
// Look for a property with the same name.
- DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
- return;
- }
+ if (ObjCPropertyDecl *ProtoProp =
+ Proto->lookup(Prop->getDeclName()).find_first<ObjCPropertyDecl>()) {
+ S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
+ return;
}
// Check this property against any protocols we inherit.
@@ -233,18 +231,13 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
bool FoundInSuper = false;
ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
- DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
- FoundInSuper = true;
- break;
- }
- }
- if (FoundInSuper)
+ if (ObjCPropertyDecl *SuperProp =
+ Super->lookup(Res->getDeclName()).find_first<ObjCPropertyDecl>()) {
+ DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
+ FoundInSuper = true;
break;
- else
- CurrentInterfaceDecl = Super;
+ }
+ CurrentInterfaceDecl = Super;
}
if (FoundInSuper) {
@@ -1149,14 +1142,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// redeclared 'readwrite', then no warning is to be issued.
for (auto *Ext : IDecl->known_extensions()) {
DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
- if (!R.empty())
- if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
- PIkind = ExtProp->getPropertyAttributesAsWritten();
- if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
- ReadWriteProperty = true;
- break;
- }
+ if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) {
+ PIkind = ExtProp->getPropertyAttributesAsWritten();
+ if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
+ ReadWriteProperty = true;
+ break;
}
+ }
}
if (!ReadWriteProperty) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8bd812b..578a77a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3420,7 +3420,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
Instantiation->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
- FieldDecl *Pattern = cast<FieldDecl>(Lookup.front());
+ FieldDecl *Pattern = Lookup.find_first<FieldDecl>();
+ assert(Pattern);
InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
TemplateArgs);
}