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);
}
Exemple #2
0
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);
}