void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations // from being visible? if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter()) return; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (FD->isFunctionTemplateSpecialization()) return; DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) { PrimaryContext->makeDeclVisibleInContext(D, Recoverable); return; } // If we already have a lookup data structure, perform the insertion // into it. If we haven't deserialized externally stored decls, deserialize // them so we can add the decl. Otherwise, be lazy and don't build that // structure until someone asks for it. if (LookupPtr || !Recoverable || hasExternalVisibleStorage()) makeDeclVisibleInContextImpl(D); // If we are a transparent context or inline namespace, insert into our // parent context, too. This operation is recursive. if (isTransparentContext() || isInlineNamespace()) getParent()->makeDeclVisibleInContext(D, Recoverable); Decl *DCAsDecl = cast<Decl>(this); // Notify that a decl was made visible unless it's a Tag being defined. if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined())) if (ASTMutationListener *L = DCAsDecl->getASTMutationListener()) L->AddedVisibleDecl(this, D); }
void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Recoverable) { assert(this == getPrimaryContext() && "expected a primary DC"); // Skip declarations within functions. // FIXME: We shouldn't need to build lookup tables for function declarations // ever, and we can't do so correctly because we can't model the nesting of // scopes which occurs within functions. We use "qualified" lookup into // function declarations when handling friend declarations inside nested // classes, and consequently accept the following invalid code: // // void f() { void g(); { int g; struct S { friend void g(); }; } } if (isFunctionOrMethod() && !isa<FunctionDecl>(D)) return; // Skip declarations which should be invisible to name lookup. if (shouldBeHidden(D)) return; // If we already have a lookup data structure, perform the insertion into // it. If we might have externally-stored decls with this name, look them // up and perform the insertion. If this decl was declared outside its // semantic context, buildLookup won't add it, so add it now. // // FIXME: As a performance hack, don't add such decls into the translation // unit unless we're in C++, since qualified lookup into the TU is never // performed. if (LookupPtr.getPointer() || hasExternalVisibleStorage() || ((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) && (getParentASTContext().getLangOpts().CPlusPlus || !isTranslationUnit()))) { // If we have lazily omitted any decls, they might have the same name as // the decl which we are adding, so build a full lookup table before adding // this decl. buildLookup(); makeDeclVisibleInContextImpl(D, Internal); } else { LookupPtr.setInt(true); } // If we are a transparent context or inline namespace, insert into our // parent context, too. This operation is recursive. if (isTransparentContext() || isInlineNamespace()) getParent()->getPrimaryContext()-> makeDeclVisibleInContextWithFlags(D, Internal, Recoverable); Decl *DCAsDecl = cast<Decl>(this); // Notify that a decl was made visible unless we are a Tag being defined. if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined())) if (ASTMutationListener *L = DCAsDecl->getASTMutationListener()) L->AddedVisibleDecl(this, D); }