Path: blob/main/contrib/llvm-project/clang/lib/Sema/IdentifierResolver.cpp
35233 views
//===- IdentifierResolver.cpp - Lexical Scope Name lookup -----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the IdentifierResolver class, which is used for lexical9// scoped lookup, based on declaration names.10//11//===----------------------------------------------------------------------===//1213#include "clang/Sema/IdentifierResolver.h"14#include "clang/AST/Decl.h"15#include "clang/AST/DeclBase.h"16#include "clang/AST/DeclarationName.h"17#include "clang/Basic/IdentifierTable.h"18#include "clang/Basic/LangOptions.h"19#include "clang/Lex/ExternalPreprocessorSource.h"20#include "clang/Lex/Preprocessor.h"21#include "clang/Sema/Scope.h"22#include "llvm/Support/ErrorHandling.h"23#include <cassert>24#include <cstdint>2526using namespace clang;2728//===----------------------------------------------------------------------===//29// IdDeclInfoMap class30//===----------------------------------------------------------------------===//3132/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.33/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each34/// individual IdDeclInfo to heap.35class IdentifierResolver::IdDeclInfoMap {36static const unsigned int POOL_SIZE = 512;3738/// We use our own linked-list implementation because it is sadly39/// impossible to add something to a pre-C++0x STL container without40/// a completely unnecessary copy.41struct IdDeclInfoPool {42IdDeclInfoPool *Next;43IdDeclInfo Pool[POOL_SIZE];4445IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}46};4748IdDeclInfoPool *CurPool = nullptr;49unsigned int CurIndex = POOL_SIZE;5051public:52IdDeclInfoMap() = default;5354~IdDeclInfoMap() {55IdDeclInfoPool *Cur = CurPool;56while (IdDeclInfoPool *P = Cur) {57Cur = Cur->Next;58delete P;59}60}6162IdDeclInfoMap(const IdDeclInfoMap &) = delete;63IdDeclInfoMap &operator=(const IdDeclInfoMap &) = delete;6465/// Returns the IdDeclInfo associated to the DeclarationName.66/// It creates a new IdDeclInfo if one was not created before for this id.67IdDeclInfo &operator[](DeclarationName Name);68};6970//===----------------------------------------------------------------------===//71// IdDeclInfo Implementation72//===----------------------------------------------------------------------===//7374/// RemoveDecl - Remove the decl from the scope chain.75/// The decl must already be part of the decl chain.76void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {77for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {78if (D == *(I-1)) {79Decls.erase(I-1);80return;81}82}8384llvm_unreachable("Didn't find this decl on its identifier's chain!");85}8687//===----------------------------------------------------------------------===//88// IdentifierResolver Implementation89//===----------------------------------------------------------------------===//9091IdentifierResolver::IdentifierResolver(Preprocessor &PP)92: LangOpt(PP.getLangOpts()), PP(PP), IdDeclInfos(new IdDeclInfoMap) {}9394IdentifierResolver::~IdentifierResolver() {95delete IdDeclInfos;96}9798/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true99/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns100/// true if 'D' belongs to the given declaration context.101bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,102bool AllowInlineNamespace) const {103Ctx = Ctx->getRedeclContext();104// The names for HLSL cbuffer/tbuffers only used by the CPU-side105// reflection API which supports querying bindings. It will not have name106// conflict with other Decls.107if (LangOpt.HLSL && isa<HLSLBufferDecl>(D))108return false;109if (Ctx->isFunctionOrMethod() || (S && S->isFunctionPrototypeScope())) {110// Ignore the scopes associated within transparent declaration contexts.111while (S->getEntity() &&112(S->getEntity()->isTransparentContext() ||113(!LangOpt.CPlusPlus && isa<RecordDecl>(S->getEntity()))))114S = S->getParent();115116if (S->isDeclScope(D))117return true;118if (LangOpt.CPlusPlus) {119// C++ 3.3.2p3:120// The name declared in a catch exception-declaration is local to the121// handler and shall not be redeclared in the outermost block of the122// handler.123// C++ 3.3.2p4:124// Names declared in the for-init-statement, and in the condition of if,125// while, for, and switch statements are local to the if, while, for, or126// switch statement (including the controlled statement), and shall not be127// redeclared in a subsequent condition of that statement nor in the128// outermost block (or, for the if statement, any of the outermost blocks)129// of the controlled statement.130//131assert(S->getParent() && "No TUScope?");132// If the current decl is in a lambda, we shouldn't consider this is a133// redefinition as lambda has its own scope.134if (S->getParent()->isControlScope() && !S->isFunctionScope()) {135S = S->getParent();136if (S->isDeclScope(D))137return true;138}139if (S->isFnTryCatchScope())140return S->getParent()->isDeclScope(D);141}142return false;143}144145// FIXME: If D is a local extern declaration, this check doesn't make sense;146// we should be checking its lexical context instead in that case, because147// that is its scope.148DeclContext *DCtx = D->getDeclContext()->getRedeclContext();149return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)150: Ctx->Equals(DCtx);151}152153/// AddDecl - Link the decl to its shadowed decl chain.154void IdentifierResolver::AddDecl(NamedDecl *D) {155DeclarationName Name = D->getDeclName();156if (IdentifierInfo *II = Name.getAsIdentifierInfo())157updatingIdentifier(*II);158159void *Ptr = Name.getFETokenInfo();160161if (!Ptr) {162Name.setFETokenInfo(D);163return;164}165166IdDeclInfo *IDI;167168if (isDeclPtr(Ptr)) {169Name.setFETokenInfo(nullptr);170IDI = &(*IdDeclInfos)[Name];171NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);172IDI->AddDecl(PrevD);173} else174IDI = toIdDeclInfo(Ptr);175176IDI->AddDecl(D);177}178179void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {180DeclarationName Name = D->getDeclName();181if (IdentifierInfo *II = Name.getAsIdentifierInfo())182updatingIdentifier(*II);183184void *Ptr = Name.getFETokenInfo();185186if (!Ptr) {187AddDecl(D);188return;189}190191if (isDeclPtr(Ptr)) {192// We only have a single declaration: insert before or after it,193// as appropriate.194if (Pos == iterator()) {195// Add the new declaration before the existing declaration.196NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);197RemoveDecl(PrevD);198AddDecl(D);199AddDecl(PrevD);200} else {201// Add new declaration after the existing declaration.202AddDecl(D);203}204205return;206}207208// General case: insert the declaration at the appropriate point in the209// list, which already has at least two elements.210IdDeclInfo *IDI = toIdDeclInfo(Ptr);211if (Pos.isIterator()) {212IDI->InsertDecl(Pos.getIterator() + 1, D);213} else214IDI->InsertDecl(IDI->decls_begin(), D);215}216217/// RemoveDecl - Unlink the decl from its shadowed decl chain.218/// The decl must already be part of the decl chain.219void IdentifierResolver::RemoveDecl(NamedDecl *D) {220assert(D && "null param passed");221DeclarationName Name = D->getDeclName();222if (IdentifierInfo *II = Name.getAsIdentifierInfo())223updatingIdentifier(*II);224225void *Ptr = Name.getFETokenInfo();226227assert(Ptr && "Didn't find this decl on its identifier's chain!");228229if (isDeclPtr(Ptr)) {230assert(D == Ptr && "Didn't find this decl on its identifier's chain!");231Name.setFETokenInfo(nullptr);232return;233}234235return toIdDeclInfo(Ptr)->RemoveDecl(D);236}237238llvm::iterator_range<IdentifierResolver::iterator>239IdentifierResolver::decls(DeclarationName Name) {240return {begin(Name), end()};241}242243IdentifierResolver::iterator IdentifierResolver::begin(DeclarationName Name) {244if (IdentifierInfo *II = Name.getAsIdentifierInfo())245readingIdentifier(*II);246247void *Ptr = Name.getFETokenInfo();248if (!Ptr) return end();249250if (isDeclPtr(Ptr))251return iterator(static_cast<NamedDecl*>(Ptr));252253IdDeclInfo *IDI = toIdDeclInfo(Ptr);254255IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();256if (I != IDI->decls_begin())257return iterator(I-1);258// No decls found.259return end();260}261262namespace {263264enum DeclMatchKind {265DMK_Different,266DMK_Replace,267DMK_Ignore268};269270} // namespace271272/// Compare two declarations to see whether they are different or,273/// if they are the same, whether the new declaration should replace the274/// existing declaration.275static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {276// If the declarations are identical, ignore the new one.277if (Existing == New)278return DMK_Ignore;279280// If the declarations have different kinds, they're obviously different.281if (Existing->getKind() != New->getKind())282return DMK_Different;283284// If the declarations are redeclarations of each other, keep the newest one.285if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {286// If we're adding an imported declaration, don't replace another imported287// declaration.288if (Existing->isFromASTFile() && New->isFromASTFile())289return DMK_Different;290291// If either of these is the most recent declaration, use it.292Decl *MostRecent = Existing->getMostRecentDecl();293if (Existing == MostRecent)294return DMK_Ignore;295296if (New == MostRecent)297return DMK_Replace;298299// If the existing declaration is somewhere in the previous declaration300// chain of the new declaration, then prefer the new declaration.301for (auto *RD : New->redecls()) {302if (RD == Existing)303return DMK_Replace;304305if (RD->isCanonicalDecl())306break;307}308309return DMK_Ignore;310}311312return DMK_Different;313}314315bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){316if (IdentifierInfo *II = Name.getAsIdentifierInfo())317readingIdentifier(*II);318319void *Ptr = Name.getFETokenInfo();320321if (!Ptr) {322Name.setFETokenInfo(D);323return true;324}325326IdDeclInfo *IDI;327328if (isDeclPtr(Ptr)) {329NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);330331switch (compareDeclarations(PrevD, D)) {332case DMK_Different:333break;334335case DMK_Ignore:336return false;337338case DMK_Replace:339Name.setFETokenInfo(D);340return true;341}342343Name.setFETokenInfo(nullptr);344IDI = &(*IdDeclInfos)[Name];345346// If the existing declaration is not visible in translation unit scope,347// then add the new top-level declaration first.348if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {349IDI->AddDecl(D);350IDI->AddDecl(PrevD);351} else {352IDI->AddDecl(PrevD);353IDI->AddDecl(D);354}355return true;356}357358IDI = toIdDeclInfo(Ptr);359360// See whether this declaration is identical to any existing declarations.361// If not, find the right place to insert it.362for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),363IEnd = IDI->decls_end();364I != IEnd; ++I) {365366switch (compareDeclarations(*I, D)) {367case DMK_Different:368break;369370case DMK_Ignore:371return false;372373case DMK_Replace:374*I = D;375return true;376}377378if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {379// We've found a declaration that is not visible from the translation380// unit (it's in an inner scope). Insert our declaration here.381IDI->InsertDecl(I, D);382return true;383}384}385386// Add the declaration to the end.387IDI->AddDecl(D);388return true;389}390391void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {392if (II.isOutOfDate())393PP.getExternalSource()->updateOutOfDateIdentifier(II);394}395396void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {397if (II.isOutOfDate())398PP.getExternalSource()->updateOutOfDateIdentifier(II);399400if (II.isFromAST())401II.setFETokenInfoChangedSinceDeserialization();402}403404//===----------------------------------------------------------------------===//405// IdDeclInfoMap Implementation406//===----------------------------------------------------------------------===//407408/// Returns the IdDeclInfo associated to the DeclarationName.409/// It creates a new IdDeclInfo if one was not created before for this id.410IdentifierResolver::IdDeclInfo &411IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {412void *Ptr = Name.getFETokenInfo();413414if (Ptr) return *toIdDeclInfo(Ptr);415416if (CurIndex == POOL_SIZE) {417CurPool = new IdDeclInfoPool(CurPool);418CurIndex = 0;419}420IdDeclInfo *IDI = &CurPool->Pool[CurIndex];421Name.setFETokenInfo(reinterpret_cast<void*>(422reinterpret_cast<uintptr_t>(IDI) | 0x1)423);424++CurIndex;425return *IDI;426}427428void IdentifierResolver::iterator::incrementSlowCase() {429NamedDecl *D = **this;430void *InfoPtr = D->getDeclName().getFETokenInfo();431assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");432IdDeclInfo *Info = toIdDeclInfo(InfoPtr);433434BaseIter I = getIterator();435if (I != Info->decls_begin())436*this = iterator(I-1);437else // No more decls.438*this = iterator();439}440441442