Example #1
0
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
                                  CXXBasePaths &Paths,
                                  bool LookupInDependent) const {
  // If we didn't find anything, report that.
  if (!Paths.lookupInBases(getASTContext(), this, BaseMatches,
                           LookupInDependent))
    return false;

  // If we're not recording paths or we won't ever find ambiguities,
  // we're done.
  if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
    return true;
  
  // C++ [class.member.lookup]p6:
  //   When virtual base classes are used, a hidden declaration can be
  //   reached along a path through the sub-object lattice that does
  //   not pass through the hiding declaration. This is not an
  //   ambiguity. The identical use with nonvirtual base classes is an
  //   ambiguity; in that case there is no unique instance of the name
  //   that hides all the others.
  //
  // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
  // way to make it any faster.
  Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
    for (const CXXBasePathElement &PE : Path) {
      if (!PE.Base->isVirtual())
        continue;

      CXXRecordDecl *VBase = nullptr;
      if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
        VBase = cast<CXXRecordDecl>(Record->getDecl());
      if (!VBase)
        break;

      // The declaration(s) we found along this path were found in a
      // subobject of a virtual base. Check whether this virtual
      // base is a subobject of any other path; if so, then the
      // declaration in this path are hidden by that patch.
      for (const CXXBasePath &HidingP : Paths) {
        CXXRecordDecl *HidingClass = nullptr;
        if (const RecordType *Record =
                HidingP.back().Base->getType()->getAs<RecordType>())
          HidingClass = cast<CXXRecordDecl>(Record->getDecl());
        if (!HidingClass)
          break;

        if (HidingClass->isVirtuallyDerivedFrom(VBase))
          return true;
      }
    }
    return false;
  });

  return true;
}
Example #2
0
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
                                  void *UserData,
                                  CXXBasePaths &Paths) const {
  // If we didn't find anything, report that.
  if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData))
    return false;

  // If we're not recording paths or we won't ever find ambiguities,
  // we're done.
  if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
    return true;
  
  // C++ [class.member.lookup]p6:
  //   When virtual base classes are used, a hidden declaration can be
  //   reached along a path through the sub-object lattice that does
  //   not pass through the hiding declaration. This is not an
  //   ambiguity. The identical use with nonvirtual base classes is an
  //   ambiguity; in that case there is no unique instance of the name
  //   that hides all the others.
  //
  // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
  // way to make it any faster.
  for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end();
       P != PEnd; /* increment in loop */) {
    bool Hidden = false;

    for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end();
         PE != PEEnd && !Hidden; ++PE) {
      if (PE->Base->isVirtual()) {
        CXXRecordDecl *VBase = 0;
        if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>())
          VBase = cast<CXXRecordDecl>(Record->getDecl());
        if (!VBase)
          break;

        // The declaration(s) we found along this path were found in a
        // subobject of a virtual base. Check whether this virtual
        // base is a subobject of any other path; if so, then the
        // declaration in this path are hidden by that patch.
        for (CXXBasePaths::paths_iterator HidingP = Paths.begin(),
                                       HidingPEnd = Paths.end();
             HidingP != HidingPEnd;
             ++HidingP) {
          CXXRecordDecl *HidingClass = 0;
          if (const RecordType *Record
                       = HidingP->back().Base->getType()->getAs<RecordType>())
            HidingClass = cast<CXXRecordDecl>(Record->getDecl());
          if (!HidingClass)
            break;

          if (HidingClass->isVirtuallyDerivedFrom(VBase)) {
            Hidden = true;
            break;
          }
        }
      }
    }

    if (Hidden)
      P = Paths.Paths.erase(P);
    else
      ++P;
  }
  
  return true;
}