diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/AST/DeclBase.cpp | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Notes
Diffstat (limited to 'lib/AST/DeclBase.cpp')
-rw-r--r-- | lib/AST/DeclBase.cpp | 135 |
1 files changed, 100 insertions, 35 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 700ddd389ddd3..b83082e9eb08c 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -153,12 +153,12 @@ void Decl::setInvalidDecl(bool Invalid) { } const char *DeclContext::getDeclKindName() const { - switch (DeclKind) { - default: llvm_unreachable("Declaration context not in DeclNodes.inc!"); + switch (getDeclKind()) { #define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" } + llvm_unreachable("Declaration context not in DeclNodes.inc!"); } bool Decl::StatisticsEnabled = false; @@ -810,6 +810,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPRequires: case OMPCapturedExpr: case Empty: // Never looked up by name. @@ -836,6 +837,29 @@ void Decl::dropAttrs() { getASTContext().eraseDeclAttrs(this); } +void Decl::addAttr(Attr *A) { + if (!hasAttrs()) { + setAttrs(AttrVec(1, A)); + return; + } + + AttrVec &Attrs = getAttrs(); + if (!A->isInherited()) { + Attrs.push_back(A); + return; + } + + // Attribute inheritance is processed after attribute parsing. To keep the + // order as in the source code, add inherited attributes before non-inherited + // ones. + auto I = Attrs.begin(), E = Attrs.end(); + for (; I != E; ++I) { + if (!(*I)->isInherited()) + break; + } + Attrs.insert(I, A); +} + const AttrVec &Decl::getAttrs() const { assert(HasAttrs && "No attrs to get!"); return getASTContext().getDeclAttrs(this); @@ -930,6 +954,10 @@ bool Decl::AccessDeclContextSanity() const { static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } +int64_t Decl::getID() const { + return getASTContext().getAllocator().identifyKnownAlignedObject<Decl>(this); +} + const FunctionType *Decl::getFunctionType(bool BlocksToo) const { QualType Ty; if (const auto *D = dyn_cast<ValueDecl>(this)) @@ -980,6 +1008,16 @@ Decl *DeclContext::getNonClosureAncestor() { // DeclContext Implementation //===----------------------------------------------------------------------===// +DeclContext::DeclContext(Decl::Kind K) { + DeclContextBits.DeclKind = K; + setHasExternalLexicalStorage(false); + setHasExternalVisibleStorage(false); + setNeedToReconcileExternalVisibleStorage(false); + setHasLazyLocalLexicalLookups(false); + setHasLazyExternalLexicalLookups(false); + setUseQualifiedLookup(false); +} + bool DeclContext::classof(const Decl *D) { switch (D->getKind()) { #define DECL(NAME, BASE) @@ -1007,7 +1045,7 @@ DeclContext::~DeclContext() = default; /// a friend function the parent lookup context is the lexical context, which /// is the class in which the friend is declared. DeclContext *DeclContext::getLookupParent() { - // FIXME: Find a better way to identify friends + // FIXME: Find a better way to identify friends. if (isa<FunctionDecl>(this)) if (getParent()->getRedeclContext()->isFileContext() && getLexicalParent()->getRedeclContext()->isRecord()) @@ -1070,9 +1108,9 @@ bool DeclContext::isDependentContext() const { } bool DeclContext::isTransparentContext() const { - if (DeclKind == Decl::Enum) + if (getDeclKind() == Decl::Enum) return !cast<EnumDecl>(this)->isScoped(); - else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export) + else if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export) return true; return false; @@ -1118,7 +1156,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const { } DeclContext *DeclContext::getPrimaryContext() { - switch (DeclKind) { + switch (getDeclKind()) { case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: @@ -1154,7 +1192,7 @@ DeclContext *DeclContext::getPrimaryContext() { return this; default: - if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) { + if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. auto *Tag = cast<TagDecl>(this); @@ -1174,7 +1212,8 @@ DeclContext *DeclContext::getPrimaryContext() { return Tag; } - assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction && + assert(getDeclKind() >= Decl::firstFunction && + getDeclKind() <= Decl::lastFunction && "Unknown DeclContext kind"); return this; } @@ -1184,7 +1223,7 @@ void DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){ Contexts.clear(); - if (DeclKind != Decl::Namespace) { + if (getDeclKind() != Decl::Namespace) { Contexts.push_back(this); return; } @@ -1222,8 +1261,8 @@ DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls, /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. void DeclContext::reconcileExternalVisibleStorage() const { - assert(NeedToReconcileExternalVisibleStorage && LookupPtr); - NeedToReconcileExternalVisibleStorage = false; + assert(hasNeedToReconcileExternalVisibleStorage() && LookupPtr); + setNeedToReconcileExternalVisibleStorage(false); for (auto &Lookup : *LookupPtr) Lookup.second.setHasExternalDecls(); @@ -1242,7 +1281,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Load the external declarations, if any. SmallVector<Decl*, 64> Decls; - ExternalLexicalStorage = false; + setHasExternalLexicalStorage(false); Source->FindExternalLexicalDecls(this, Decls); if (Decls.empty()) @@ -1252,7 +1291,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // we need to ignore them. bool FieldsAlreadyLoaded = false; if (const auto *RD = dyn_cast<RecordDecl>(this)) - FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage; + FieldsAlreadyLoaded = RD->hasLoadedFieldsFromExternalStorage(); // Splice the newly-read declarations into the beginning of the list // of declarations. @@ -1273,7 +1312,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); - if (DC->NeedToReconcileExternalVisibleStorage) + if (DC->hasNeedToReconcileExternalVisibleStorage()) DC->reconcileExternalVisibleStorage(); (*Map)[Name].removeExternalDecls(); @@ -1289,7 +1328,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); - if (DC->NeedToReconcileExternalVisibleStorage) + if (DC->hasNeedToReconcileExternalVisibleStorage()) DC->reconcileExternalVisibleStorage(); StoredDeclsList &List = (*Map)[Name]; @@ -1366,6 +1405,12 @@ static bool shouldBeHidden(NamedDecl *D) { D->isTemplateParameter()) return true; + // Skip friends and local extern declarations unless they're the first + // declaration of the entity. + if ((D->isLocalExternDecl() || D->getFriendObjectKind()) && + D != D->getCanonicalDecl()) + return true; + // Skip template specializations. // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations @@ -1424,7 +1469,9 @@ void DeclContext::removeDecl(Decl *D) { if (Map) { StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); assert(Pos != Map->end() && "no lookup entry for decl"); - if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND) + // Remove the decl only if it is contained. + StoredDeclsList::DeclsTy *Vec = Pos->second.getAsVector(); + if ((Vec && is_contained(*Vec, ND)) || Pos->second.getAsDecl() == ND) Pos->second.remove(ND); } } while (DC->isTransparentContext() && (DC = DC->getParent())); @@ -1483,21 +1530,24 @@ void DeclContext::addDeclInternal(Decl *D) { StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); - if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) + if (!hasLazyLocalLexicalLookups() && + !hasLazyExternalLexicalLookups()) return LookupPtr; SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); - if (HasLazyExternalLexicalLookups) { - HasLazyExternalLexicalLookups = false; + if (hasLazyExternalLexicalLookups()) { + setHasLazyExternalLexicalLookups(false); for (auto *DC : Contexts) { - if (DC->hasExternalLexicalStorage()) - HasLazyLocalLexicalLookups |= - DC->LoadLexicalDeclsFromExternalStorage(); + if (DC->hasExternalLexicalStorage()) { + bool LoadedDecls = DC->LoadLexicalDeclsFromExternalStorage(); + setHasLazyLocalLexicalLookups( + hasLazyLocalLexicalLookups() | LoadedDecls ); + } } - if (!HasLazyLocalLexicalLookups) + if (!hasLazyLocalLexicalLookups()) return LookupPtr; } @@ -1505,7 +1555,7 @@ StoredDeclsMap *DeclContext::buildLookup() { buildLookupImpl(DC, hasExternalVisibleStorage()); // We no longer have any lazy decls. - HasLazyLocalLexicalLookups = false; + setHasLazyLocalLexicalLookups(false); return LookupPtr; } @@ -1543,7 +1593,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr; DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) const { - assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + assert(getDeclKind() != Decl::LinkageSpec && + getDeclKind() != Decl::Export && "should not perform lookups into transparent contexts"); const DeclContext *PrimaryContext = getPrimaryContext(); @@ -1560,12 +1611,13 @@ DeclContext::lookup(DeclarationName Name) const { if (hasExternalVisibleStorage()) { assert(Source && "external visible storage but no external source?"); - if (NeedToReconcileExternalVisibleStorage) + if (hasNeedToReconcileExternalVisibleStorage()) reconcileExternalVisibleStorage(); StoredDeclsMap *Map = LookupPtr; - if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + if (hasLazyLocalLexicalLookups() || + hasLazyExternalLexicalLookups()) // FIXME: Make buildLookup const? Map = const_cast<DeclContext*>(this)->buildLookup(); @@ -1590,7 +1642,8 @@ DeclContext::lookup(DeclarationName Name) const { } StoredDeclsMap *Map = LookupPtr; - if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + if (hasLazyLocalLexicalLookups() || + hasLazyExternalLexicalLookups()) Map = const_cast<DeclContext*>(this)->buildLookup(); if (!Map) @@ -1605,7 +1658,8 @@ DeclContext::lookup(DeclarationName Name) const { DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + assert(getDeclKind() != Decl::LinkageSpec && + getDeclKind() != Decl::Export && "should not perform lookups into transparent contexts"); DeclContext *PrimaryContext = getPrimaryContext(); @@ -1626,12 +1680,12 @@ DeclContext::noload_lookup(DeclarationName Name) { // now. Don't import any external declarations, not even if we know we have // some missing from the external visible lookups. void DeclContext::loadLazyLocalLexicalLookups() { - if (HasLazyLocalLexicalLookups) { + if (hasLazyLocalLexicalLookups()) { SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); for (auto *Context : Contexts) buildLookupImpl(Context, hasExternalVisibleStorage()); - HasLazyLocalLexicalLookups = false; + setHasLazyLocalLexicalLookups(false); } } @@ -1649,7 +1703,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name, // If we have a lookup table, check there first. Maybe we'll get lucky. // FIXME: Should we be checking these flags on the primary context? - if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) { + if (Name && !hasLazyLocalLexicalLookups() && + !hasLazyExternalLexicalLookups()) { if (StoredDeclsMap *Map = LookupPtr) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { @@ -1674,8 +1729,18 @@ void DeclContext::localUncachedLookup(DeclarationName Name, DeclContext *DeclContext::getRedeclContext() { DeclContext *Ctx = this; - // Skip through transparent contexts. - while (Ctx->isTransparentContext()) + + // In C, a record type is the redeclaration context for its fields only. If + // we arrive at a record context after skipping anything else, we should skip + // the record as well. Currently, this means skipping enumerations because + // they're the only transparent context that can exist within a struct or + // union. + bool SkipRecords = getDeclKind() == Decl::Kind::Enum && + !getParentASTContext().getLangOpts().CPlusPlus; + + // Skip through contexts to get to the redeclaration context. Transparent + // contexts are always skipped. + while ((SkipRecords && Ctx->isRecord()) || Ctx->isTransparentContext()) Ctx = Ctx->getParent(); return Ctx; } @@ -1758,7 +1823,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, buildLookup(); makeDeclVisibleInContextImpl(D, Internal); } else { - HasLazyLocalLexicalLookups = true; + setHasLazyLocalLexicalLookups(true); } // If we are a transparent context or inline namespace, insert into our |