diff options
Diffstat (limited to 'lib/AST/DeclBase.cpp')
| -rw-r--r-- | lib/AST/DeclBase.cpp | 195 | 
1 files changed, 137 insertions, 58 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 084a4321d8f1..121c5a671a29 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -291,6 +291,16 @@ bool Decl::isUsed(bool CheckUsedAttr) const {    return false;   } +void Decl::markUsed(ASTContext &C) { +  if (Used) +    return; + +  if (C.getASTMutationListener()) +    C.getASTMutationListener()->DeclarationMarkedUsed(this); + +  Used = true; +} +  bool Decl::isReferenced() const {     if (Referenced)      return true; @@ -538,6 +548,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {        return IDNS_Namespace;      case FunctionTemplate: +    case VarTemplate:        return IDNS_Ordinary;      case ClassTemplate: @@ -560,6 +571,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {      case ClassTemplateSpecialization:      case ClassTemplatePartialSpecialization:      case ClassScopeFunctionSpecialization: +    case VarTemplateSpecialization: +    case VarTemplatePartialSpecialization:      case ObjCImplementation:      case ObjCCategory:      case ObjCCategoryImpl: @@ -595,32 +608,6 @@ const AttrVec &Decl::getAttrs() const {    return getASTContext().getDeclAttrs(this);  } -void Decl::swapAttrs(Decl *RHS) { -  bool HasLHSAttr = this->HasAttrs; -  bool HasRHSAttr = RHS->HasAttrs; - -  // Usually, neither decl has attrs, nothing to do. -  if (!HasLHSAttr && !HasRHSAttr) return; - -  // If 'this' has no attrs, swap the other way. -  if (!HasLHSAttr) -    return RHS->swapAttrs(this); - -  ASTContext &Context = getASTContext(); - -  // Handle the case when both decls have attrs. -  if (HasRHSAttr) { -    std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS)); -    return; -  } - -  // Otherwise, LHS has an attr and RHS doesn't. -  Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this); -  Context.eraseDeclAttrs(this); -  this->HasAttrs = false; -  RHS->HasAttrs = true; -} -  Decl *Decl::castFromDeclContext (const DeclContext *D) {    Decl::Kind DK = D->getDeclKind();    switch(DK) { @@ -819,6 +806,24 @@ bool DeclContext::isTransparentContext() const {    return false;  } +static bool isLinkageSpecContext(const DeclContext *DC, +                                 LinkageSpecDecl::LanguageIDs ID) { +  while (DC->getDeclKind() != Decl::TranslationUnit) { +    if (DC->getDeclKind() == Decl::LinkageSpec) +      return cast<LinkageSpecDecl>(DC)->getLanguage() == ID; +    DC = DC->getParent(); +  } +  return false; +} + +bool DeclContext::isExternCContext() const { +  return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c); +} + +bool DeclContext::isExternCXXContext() const { +  return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); +} +  bool DeclContext::Encloses(const DeclContext *DC) const {    if (getPrimaryContext() != this)      return getPrimaryContext()->Encloses(DC); @@ -939,11 +944,8 @@ void DeclContext::reconcileExternalVisibleStorage() {    NeedToReconcileExternalVisibleStorage = false;    StoredDeclsMap &Map = *LookupPtr.getPointer(); -  ExternalASTSource *Source = getParentASTContext().getExternalSource(); -  for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) { -    I->second.removeExternalDecls(); -    Source->FindExternalVisibleDeclsByName(this, I->first); -  } +  for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) +    I->second.setHasExternalDecls();  }  /// \brief Load the declarations within this lexical storage from an @@ -996,8 +998,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,    if (!(Map = DC->LookupPtr.getPointer()))      Map = DC->CreateStoredDeclsMap(Context); -  // Add an entry to the map for this name, if it's not already present. -  (*Map)[Name]; +  (*Map)[Name].removeExternalDecls();    return DeclContext::lookup_result();  } @@ -1012,13 +1013,38 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,      Map = DC->CreateStoredDeclsMap(Context);    StoredDeclsList &List = (*Map)[Name]; -  for (ArrayRef<NamedDecl*>::iterator -         I = Decls.begin(), E = Decls.end(); I != E; ++I) { -    if (List.isNull()) -      List.setOnlyValue(*I); -    else -      // FIXME: Need declarationReplaces handling for redeclarations in modules. -      List.AddSubsequentDecl(*I); + +  // Clear out any old external visible declarations, to avoid quadratic +  // performance in the redeclaration checks below. +  List.removeExternalDecls(); + +  if (!List.isNull()) { +    // We have both existing declarations and new declarations for this name. +    // Some of the declarations may simply replace existing ones. Handle those +    // first. +    llvm::SmallVector<unsigned, 8> Skip; +    for (unsigned I = 0, N = Decls.size(); I != N; ++I) +      if (List.HandleRedeclaration(Decls[I])) +        Skip.push_back(I); +    Skip.push_back(Decls.size()); + +    // Add in any new declarations. +    unsigned SkipPos = 0; +    for (unsigned I = 0, N = Decls.size(); I != N; ++I) { +      if (I == Skip[SkipPos]) +        ++SkipPos; +      else +        List.AddSubsequentDecl(Decls[I]); +    } +  } else { +    // Convert the array to a StoredDeclsList. +    for (ArrayRef<NamedDecl*>::iterator +           I = Decls.begin(), E = Decls.end(); I != E; ++I) { +      if (List.isNull()) +        List.setOnlyValue(*I); +      else +        List.AddSubsequentDecl(*I); +    }    }    return List.getLookupResult(); @@ -1171,7 +1197,8 @@ StoredDeclsMap *DeclContext::buildLookup() {    SmallVector<DeclContext *, 2> Contexts;    collectAllContexts(Contexts);    for (unsigned I = 0, N = Contexts.size(); I != N; ++I) -    buildLookupImpl(Contexts[I]); +    buildLookupImpl<&DeclContext::decls_begin, +                    &DeclContext::decls_end>(Contexts[I]);    // We no longer have any lazy decls.    LookupPtr.setInt(false); @@ -1183,16 +1210,26 @@ StoredDeclsMap *DeclContext::buildLookup() {  /// declarations contained within DCtx, which will either be this  /// DeclContext, a DeclContext linked to it, or a transparent context  /// nested within it. +template<DeclContext::decl_iterator (DeclContext::*Begin)() const, +         DeclContext::decl_iterator (DeclContext::*End)() const>  void DeclContext::buildLookupImpl(DeclContext *DCtx) { -  for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end(); +  for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)();         I != E; ++I) {      Decl *D = *I;      // Insert this declaration into the lookup structure, but only if      // it's semantically within its decl context. Any other decls which      // should be found in this context are added eagerly. +    // +    // If it's from an AST file, don't add it now. It'll get handled by +    // FindExternalVisibleDeclsByName if needed. Exception: if we're not +    // in C++, we do not track external visible decls for the TU, so in +    // that case we need to collect them all here.      if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) -      if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND)) +      if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND) && +          (!ND->isFromASTFile() || +           (isTranslationUnit() && +            !getParentASTContext().getLangOpts().CPlusPlus)))          makeDeclVisibleInContextImpl(ND, false);      // If this declaration is itself a transparent declaration context @@ -1200,7 +1237,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) {      // context (recursively).      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))        if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) -        buildLookupImpl(InnerCtx); +        buildLookupImpl<Begin, End>(InnerCtx);    }  } @@ -1223,16 +1260,14 @@ DeclContext::lookup(DeclarationName Name) {      if (!Map)        Map = CreateStoredDeclsMap(getParentASTContext()); -    // If a PCH/module has a result for this name, and we have a local -    // declaration, we will have imported the PCH/module result when adding the -    // local declaration or when reconciling the module. +    // If we have a lookup result with no external decls, we are done.      std::pair<StoredDeclsMap::iterator, bool> R =          Map->insert(std::make_pair(Name, StoredDeclsList())); -    if (!R.second) +    if (!R.second && !R.first->second.hasExternalDecls())        return R.first->second.getLookupResult();      ExternalASTSource *Source = getParentASTContext().getExternalSource(); -    if (Source->FindExternalVisibleDeclsByName(this, Name)) { +    if (Source->FindExternalVisibleDeclsByName(this, Name) || R.second) {        if (StoredDeclsMap *Map = LookupPtr.getPointer()) {          StoredDeclsMap::iterator I = Map->find(Name);          if (I != Map->end()) @@ -1257,6 +1292,46 @@ DeclContext::lookup(DeclarationName Name) {    return I->second.getLookupResult();  } +DeclContext::lookup_result +DeclContext::noload_lookup(DeclarationName Name) { +  assert(DeclKind != Decl::LinkageSpec && +         "Should not perform lookups into linkage specs!"); +  if (!hasExternalVisibleStorage()) +    return lookup(Name); + +  DeclContext *PrimaryContext = getPrimaryContext(); +  if (PrimaryContext != this) +    return PrimaryContext->noload_lookup(Name); + +  StoredDeclsMap *Map = LookupPtr.getPointer(); +  if (LookupPtr.getInt()) { +    // Carefully build the lookup map, without deserializing anything. +    SmallVector<DeclContext *, 2> Contexts; +    collectAllContexts(Contexts); +    for (unsigned I = 0, N = Contexts.size(); I != N; ++I) +      buildLookupImpl<&DeclContext::noload_decls_begin, +                      &DeclContext::noload_decls_end>(Contexts[I]); + +    // We no longer have any lazy decls. +    LookupPtr.setInt(false); + +    // There may now be names for which we have local decls but are +    // missing the external decls. FIXME: Just set the hasExternalDecls +    // flag on those names that have external decls. +    NeedToReconcileExternalVisibleStorage = true; + +    Map = LookupPtr.getPointer(); +  } + +  if (!Map) +    return lookup_result(lookup_iterator(0), lookup_iterator(0)); + +  StoredDeclsMap::iterator I = Map->find(Name); +  return I != Map->end() +             ? I->second.getLookupResult() +             : lookup_result(lookup_iterator(0), lookup_iterator(0)); +} +  void DeclContext::localUncachedLookup(DeclarationName Name,                                        SmallVectorImpl<NamedDecl *> &Results) {    Results.clear(); @@ -1338,14 +1413,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,    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)) +  if (isFunctionOrMethod())      return;    // Skip declarations which should be invisible to name lookup. @@ -1406,7 +1474,18 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {    // Insert this declaration into the map.    StoredDeclsList &DeclNameEntries = (*Map)[D->getDeclName()]; -  if (DeclNameEntries.isNull()) { + +  if (Internal) { +    // If this is being added as part of loading an external declaration, +    // this may not be the only external declaration with this name. +    // In this case, we never try to replace an existing declaration; we'll +    // handle that when we finalize the list of declarations for this name. +    DeclNameEntries.setHasExternalDecls(); +    DeclNameEntries.AddSubsequentDecl(D); +    return; +  } + +  else if (DeclNameEntries.isNull()) {      DeclNameEntries.setOnlyValue(D);      return;    }  | 
