Ejemplo n.º 1
0
/// EmitStringTable - If the current symbol table is non-empty, emit the string
/// table for it
void ELFWriter::EmitStringTable(const std::string &ModuleName) {
  if (!SymbolList.size()) return;  // Empty symbol table.
  ELFSection &StrTab = getStringTableSection();

  // Set the zero'th symbol to a null byte, as required.
  StrTab.emitByte(0);

  // Walk on the symbol list and write symbol names into the string table.
  unsigned Index = 1;
  for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) {
    ELFSym &Sym = *(*I);

    std::string Name;
    if (Sym.isGlobalValue()) {
      SmallString<40> NameStr;
      Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false);
      Name.append(NameStr.begin(), NameStr.end());
    } else if (Sym.isExternalSym())
      Name.append(Sym.getExternalSymbol());
    else if (Sym.isFileType())
      Name.append(ModuleName);

    if (Name.empty()) {
      Sym.NameIdx = 0;
    } else {
      Sym.NameIdx = Index;
      StrTab.emitString(Name);

      // Keep track of the number of bytes emitted to this section.
      Index += Name.size()+1;
    }
  }
  assert(Index == StrTab.size());
  StrTab.Size = Index;
}
Ejemplo n.º 2
0
// Compute the relative path from From to To.
static std::string computeRelativePath(StringRef From, StringRef To) {
  if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
    return To;

  StringRef DirFrom = sys::path::parent_path(From);
  auto FromI = sys::path::begin(DirFrom);
  auto ToI = sys::path::begin(To);
  while (*FromI == *ToI) {
    ++FromI;
    ++ToI;
  }

  SmallString<128> Relative;
  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
    sys::path::append(Relative, "..");

  for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
    sys::path::append(Relative, *ToI);

#ifdef LLVM_ON_WIN32
  // Replace backslashes with slashes so that the path is portable between *nix
  // and Windows.
  std::replace(Relative.begin(), Relative.end(), '\\', '/');
#endif

  return Relative.str();
}
Ejemplo n.º 3
0
// Convert a path into the canonical form.
// Canonical form is either "/", or "/segment" * N:
//   C:\foo\bar --> /c:/foo/bar
//   /foo/      --> /foo
//   a/b/c      --> /a/b/c
static SmallString<128> canonicalize(StringRef Path) {
  SmallString<128> Result = Path.rtrim('/');
  native(Result, sys::path::Style::posix);
  if (Result.empty() || Result.front() != '/')
    Result.insert(Result.begin(), '/');
  return Result;
}
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
  MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());

  SmallString<128> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups());
  VecOS.flush();
  IF->getCode().append(Code.begin(), Code.end());
}
Ejemplo n.º 5
0
void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a data
  //   fragment of its own.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSectionData *SD = getCurrentSectionData();
    if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
      DF = getOrCreateDataFragment();
    else {
      DF = new MCDataFragment(SD);
      if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
        // If this is a new fragment created for a bundle-locked group, and the
        // group was marked as "align_to_end", set a flag in the fragment.
        DF->setAlignToBundleEnd(true);
      }
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    SD->setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());
}
Ejemplo n.º 6
0
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
  // Always create a new, separate fragment here, because its size can change
  // during relaxation.
  MCRelaxableFragment *IF = new MCRelaxableFragment(Inst);
  insert(IF);

  SmallString<128> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups());
  VecOS.flush();
  IF->getContents().append(Code.begin(), Code.end());
}
Ejemplo n.º 7
0
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
                                   const Diagnostic &Info)
  : ID(Info.getID()), Level(Level)
{
  assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
       "Valid source location without setting a source manager for diagnostic");
  if (Info.getLocation().isValid())
    Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
  SmallString<64> Message;
  Info.FormatDiagnostic(Message);
  this->Message.assign(Message.begin(), Message.end());
  this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
  this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
}
Ejemplo n.º 8
0
void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst,
                                          const MCSubtargetInfo &STI) {
  if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled())
    llvm_unreachable("All instructions should have already been relaxed");

  // Always create a new, separate fragment here, because its size can change
  // during relaxation.
  MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI);
  insert(IF);

  SmallString<128> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
                                                STI);
  IF->getContents().append(Code.begin(), Code.end());
}
Ejemplo n.º 9
0
void MCMachOStreamer::EmitInstToData(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {
  MCDataFragment *DF = getOrCreateDataFragment();

  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);

  // Add the fixups and data.
  for (MCFixup &Fixup : Fixups) {
    Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixup);
  }
  DF->getContents().append(Code.begin(), Code.end());
}
Ejemplo n.º 10
0
void MCMachOStreamer::EmitInstToData(const MCInst &Inst) {
  MCDataFragment *DF = getOrCreateDataFragment();

  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
  VecOS.flush();

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->addFixup(Fixups[i]);
  }
  DF->getContents().append(Code.begin(), Code.end());
}
Ejemplo n.º 11
0
HeaderSearch::LoadModuleMapResult 
HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir) {
  llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir
    = DirectoryHasModuleMap.find(Dir);
  if (KnownDir != DirectoryHasModuleMap.end())
    return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
  
  SmallString<128> ModuleMapFileName;
  ModuleMapFileName += Dir->getName();
  unsigned ModuleMapDirNameLen = ModuleMapFileName.size();
  llvm::sys::path::append(ModuleMapFileName, "module.map");
  if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) {
    // We have found a module map file. Try to parse it.
    if (ModMap.parseModuleMapFile(ModuleMapFile)) {
      // No suitable module map.
      DirectoryHasModuleMap[Dir] = false;
      return LMM_InvalidModuleMap;
    }

    // This directory has a module map.
    DirectoryHasModuleMap[Dir] = true;
    
    // Check whether there is a private module map that we need to load as well.
    ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen,
                            ModuleMapFileName.end());
    llvm::sys::path::append(ModuleMapFileName, "module_private.map");
    if (const FileEntry *PrivateModuleMapFile
                                        = FileMgr.getFile(ModuleMapFileName)) {
      if (ModMap.parseModuleMapFile(PrivateModuleMapFile)) {
        // No suitable module map.
        DirectoryHasModuleMap[Dir] = false;
        return LMM_InvalidModuleMap;
      }      
    }
    
    return LMM_NewlyLoaded;
  }
  
  // No suitable module map.
  DirectoryHasModuleMap[Dir] = false;
  return LMM_InvalidModuleMap;
}
Ejemplo n.º 12
0
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
                                   const Diagnostic &Info)
    : ID(Info.getID()), Level(Level)
{
    assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
           "Valid source location without setting a source manager for diagnostic");
    if (Info.getLocation().isValid())
        Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
    SmallString<64> Message;
    Info.FormatDiagnostic(Message);
    this->Message.assign(Message.begin(), Message.end());

    Ranges.reserve(Info.getNumRanges());
    for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
        Ranges.push_back(Info.getRange(I));

    FixIts.reserve(Info.getNumFixItHints());
    for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
        FixIts.push_back(Info.getFixItHint(I));
}
Ejemplo n.º 13
0
void MCELFStreamer::mergeFragment(MCDataFragment *DF,
                                  MCEncodedFragmentWithFixups *EF) {
  MCAssembler &Assembler = getAssembler();

  if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
    uint64_t FSize = EF->getContents().size();

    if (FSize > Assembler.getBundleAlignSize())
      report_fatal_error("Fragment can't be larger than a bundle size");

    uint64_t RequiredBundlePadding = computeBundlePadding(
        Assembler, EF, DF->getContents().size(), FSize);

    if (RequiredBundlePadding > UINT8_MAX)
      report_fatal_error("Padding cannot exceed 255 bytes");

    if (RequiredBundlePadding > 0) {
      SmallString<256> Code;
      raw_svector_ostream VecOS(Code);
      MCObjectWriter *OW = Assembler.getBackend().createObjectWriter(VecOS);

      EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));

      Assembler.writeFragmentPadding(*EF, FSize, OW);
      VecOS.flush();
      delete OW;

      DF->getContents().append(Code.begin(), Code.end());
    }
  }

  flushPendingLabels(DF, DF->getContents().size());

  for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) {
    EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() +
                                 DF->getContents().size());
    DF->getFixups().push_back(EF->getFixups()[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
}
Ejemplo n.º 14
0
/// ComputeSymbolTable - Compute the symbol table data
///
/// \param StringTable [out] - The string table data.
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
/// string table.
void MachObjectWriter::
ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
                   std::vector<MachSymbolData> &LocalSymbolData,
                   std::vector<MachSymbolData> &ExternalSymbolData,
                   std::vector<MachSymbolData> &UndefinedSymbolData) {
  // Build section lookup table.
  DenseMap<const MCSection*, uint8_t> SectionIndexMap;
  unsigned Index = 1;
  for (MCAssembler::iterator it = Asm.begin(),
         ie = Asm.end(); it != ie; ++it, ++Index)
    SectionIndexMap[&it->getSection()] = Index;
  assert(Index <= 256 && "Too many sections!");

  // Index 0 is always the empty string.
  StringMap<uint64_t> StringIndexMap;
  StringTable += '\x00';

  // Build the symbol arrays and the string table, but only for non-local
  // symbols.
  //
  // The particular order that we collect the symbols and create the string
  // table, then sort the symbols is chosen to match 'as'. Even though it
  // doesn't matter for correctness, this is important for letting us diff .o
  // files.
  for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
         ie = Asm.symbol_end(); it != ie; ++it) {
    const MCSymbol &Symbol = it->getSymbol();

    // Ignore non-linker visible symbols.
    if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
      continue;

    if (!it->isExternal() && !Symbol.isUndefined())
      continue;

    uint64_t &Entry = StringIndexMap[Symbol.getName()];
    if (!Entry) {
      Entry = StringTable.size();
      StringTable += Symbol.getName();
      StringTable += '\x00';
    }

    MachSymbolData MSD;
    MSD.SymbolData = it;
    MSD.StringIndex = Entry;

    if (Symbol.isUndefined()) {
      MSD.SectionIndex = 0;
      UndefinedSymbolData.push_back(MSD);
    } else if (Symbol.isAbsolute()) {
      MSD.SectionIndex = 0;
      ExternalSymbolData.push_back(MSD);
    } else {
      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
      assert(MSD.SectionIndex && "Invalid section index!");
      ExternalSymbolData.push_back(MSD);
    }
  }

  // Now add the data for local symbols.
  for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
         ie = Asm.symbol_end(); it != ie; ++it) {
    const MCSymbol &Symbol = it->getSymbol();

    // Ignore non-linker visible symbols.
    if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
      continue;

    if (it->isExternal() || Symbol.isUndefined())
      continue;

    uint64_t &Entry = StringIndexMap[Symbol.getName()];
    if (!Entry) {
      Entry = StringTable.size();
      StringTable += Symbol.getName();
      StringTable += '\x00';
    }

    MachSymbolData MSD;
    MSD.SymbolData = it;
    MSD.StringIndex = Entry;

    if (Symbol.isAbsolute()) {
      MSD.SectionIndex = 0;
      LocalSymbolData.push_back(MSD);
    } else {
      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
      assert(MSD.SectionIndex && "Invalid section index!");
      LocalSymbolData.push_back(MSD);
    }
  }

  // External and undefined symbols are required to be in lexicographic order.
  std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
  std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());

  // Set the symbol indices.
  Index = 0;
  for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
    LocalSymbolData[i].SymbolData->setIndex(Index++);
  for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
    ExternalSymbolData[i].SymbolData->setIndex(Index++);
  for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
    UndefinedSymbolData[i].SymbolData->setIndex(Index++);

  // The string table is padded to a multiple of 4.
  while (StringTable.size() % 4)
    StringTable += '\x00';
}
Ejemplo n.º 15
0
void MCELFStreamer::EmitInstToData(const MCInst &Inst,
                                   const MCSubtargetInfo &STI) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a
  //   fragment of its own. If there are no fixups registered for the
  //   instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a
  //   MCDataFragment.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSection &Sec = *getCurrentSectionOnly();
    if (Assembler.getRelaxAll() && isBundleLocked())
      // If the -mc-relax-all flag is used and we are bundle-locked, we re-use
      // the current bundle group.
      DF = BundleGroups.back();
    else if (Assembler.getRelaxAll() && !isBundleLocked())
      // When not in a bundle-locked group and the -mc-relax-all flag is used,
      // we create a new temporary fragment which will be later merged into
      // the current fragment.
      DF = new MCDataFragment();
    else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst())
      // If we are bundle-locked, we re-use the current fragment.
      // The bundle-locking directive ensures this is a new data fragment.
      DF = cast<MCDataFragment>(getCurrentFragment());
    else if (!isBundleLocked() && Fixups.size() == 0) {
      // Optimize memory usage by emitting the instruction to a
      // MCCompactEncodedInstFragment when not in a bundle-locked group and
      // there are no fixups registered.
      MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
      insert(CEIF);
      CEIF->getContents().append(Code.begin(), Code.end());
      return;
    } else {
      DF = new MCDataFragment();
      insert(DF);
    }
    if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) {
      // If this fragment is for a group marked "align_to_end", set a flag
      // in the fragment. This can happen after the fragment has already been
      // created if there are nested bundle_align groups and an inner one
      // is the one marked align_to_end.
      DF->setAlignToBundleEnd(true);
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    Sec.setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());

  if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
    if (!isBundleLocked()) {
      mergeFragment(getOrCreateDataFragment(), DF);
      delete DF;
    }
  }
}
Ejemplo n.º 16
0
Archivo: Twine.cpp Proyecto: aaasz/SHP
std::string Twine::str() const {
  SmallString<256> Vec;
  toVector(Vec);
  return std::string(Vec.begin(), Vec.end());
}
Ejemplo n.º 17
0
void SwiftLangSupport::findInterfaceDocument(StringRef ModuleName,
                                             ArrayRef<const char *> Args,
                       std::function<void(const InterfaceDocInfo &)> Receiver) {
  InterfaceDocInfo Info;

  CompilerInstance CI;
  // Display diagnostics to stderr.
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);

  CompilerInvocation Invocation;
  std::string Error;
  if (getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(),
                                             StringRef(), Error)) {
    Info.Error = Error;
    return Receiver(Info);
  }

  if (auto IFaceGenRef = IFaceGenContexts.find(ModuleName, Invocation))
    Info.ModuleInterfaceName = IFaceGenRef->getDocumentName();

  SmallString<128> Buf;
  SmallVector<std::pair<unsigned, unsigned>, 16> ArgOffs;
  auto addArgPair = [&](StringRef Arg, StringRef Val) {
    assert(!Arg.empty());
    if (Val.empty())
      return;
    unsigned ArgBegin = Buf.size();
    Buf += Arg;
    unsigned ArgEnd = Buf.size();
    unsigned ValBegin = Buf.size();
    Buf += Val;
    unsigned ValEnd = Buf.size();
    ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd));
    ArgOffs.push_back(std::make_pair(ValBegin, ValEnd));
  };
  auto addSingleArg = [&](StringRef Arg) {
    assert(!Arg.empty());
    unsigned ArgBegin = Buf.size();
    Buf += Arg;
    unsigned ArgEnd = Buf.size();
    ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd));
  };

  addArgPair("-target", Invocation.getTargetTriple());

  const auto &SPOpts = Invocation.getSearchPathOptions();
  addArgPair("-sdk", SPOpts.SDKPath);
  for (auto &Path : SPOpts.FrameworkSearchPaths)
    addArgPair("-F", Path);
  for (auto &Path : SPOpts.ImportSearchPaths)
    addArgPair("-I", Path);

  const auto &ClangOpts = Invocation.getClangImporterOptions();
  addArgPair("-module-cache-path", ClangOpts.ModuleCachePath);
  for (auto &ExtraArg : ClangOpts.ExtraArgs)
    addArgPair("-Xcc", ExtraArg);

  if (Invocation.getFrontendOptions().ImportUnderlyingModule)
    addSingleArg("-import-underlying-module");
  addArgPair("-import-objc-header",
             Invocation.getFrontendOptions().ImplicitObjCHeaderPath);

  SmallVector<StringRef, 16> NewArgs;
  for (auto Pair : ArgOffs) {
    NewArgs.push_back(StringRef(Buf.begin()+Pair.first, Pair.second-Pair.first));
  }
  Info.CompilerArgs = NewArgs;

  return Receiver(Info);
}
Ejemplo n.º 18
0
/// Returns true for failure to resolve.
static bool passCursorInfoForDecl(const ValueDecl *VD,
                                  const Module *MainModule,
                                  const Type Ty,
                                  bool IsRef,
                                  Optional<unsigned> OrigBufferID,
                                  SwiftLangSupport &Lang,
                                  const CompilerInvocation &Invok,
                            ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps,
                             std::function<void(const CursorInfo &)> Receiver) {
  if (AvailableAttr::isUnavailable(VD))
    return true;

  SmallString<64> SS;
  auto BaseType = findBaseTypeForReplacingArchetype(VD, Ty);
  unsigned NameBegin = SS.size();
  {
    llvm::raw_svector_ostream OS(SS);
    SwiftLangSupport::printDisplayName(VD, OS);
  }
  unsigned NameEnd = SS.size();

  unsigned USRBegin = SS.size();
  {
    llvm::raw_svector_ostream OS(SS);
    SwiftLangSupport::printUSR(VD, OS);
  }
  unsigned USREnd = SS.size();

  unsigned TypenameBegin = SS.size();
  if (VD->hasType()) {
    llvm::raw_svector_ostream OS(SS);
    VD->getType().print(OS);
  }
  unsigned TypenameEnd = SS.size();

  unsigned DocCommentBegin = SS.size();
  {
    llvm::raw_svector_ostream OS(SS);
    ide::getDocumentationCommentAsXML(VD, OS);
  }
  unsigned DocCommentEnd = SS.size();

  unsigned DeclBegin = SS.size();
  {
    llvm::raw_svector_ostream OS(SS);
    printAnnotatedDeclaration(VD, Ty, BaseType, OS);
  }
  unsigned DeclEnd = SS.size();

  SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs;

  ide::walkOverriddenDecls(VD,
    [&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) {
      unsigned OverUSRBegin = SS.size();
      {
        llvm::raw_svector_ostream OS(SS);
        if (auto VD = D.dyn_cast<const ValueDecl*>()) {
          if (SwiftLangSupport::printUSR(VD, OS))
            return;
        } else {
          llvm::SmallString<128> Buf;
          if (clang::index::generateUSRForDecl(
              D.get<const clang::NamedDecl*>(), Buf))
            return;
          OS << Buf.str();
        }
      }
      unsigned OverUSREnd = SS.size();
      OverUSROffs.push_back(std::make_pair(OverUSRBegin, OverUSREnd));
  });

  SmallVector<std::pair<unsigned, unsigned>, 4> RelDeclOffs;
  walkRelatedDecls(VD, [&](const ValueDecl *RelatedDecl, bool DuplicateName) {
    unsigned RelatedDeclBegin = SS.size();
    {
      llvm::raw_svector_ostream OS(SS);
      OS<<"<RelatedName usr=\"";
      SwiftLangSupport::printUSR(RelatedDecl, OS);
      OS<<"\">";
      if (isa<AbstractFunctionDecl>(RelatedDecl) && DuplicateName) {
        // Related decls are generally overloads, so print parameter types to
        // differentiate them.
        PrintOptions PO;
        PO.SkipAttributes = true;
        PO.SkipIntroducerKeywords = true;
        PO.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly;
        XMLEscapingPrinter Printer(OS);
        if (BaseType)
          PO.setArchetypeTransform(BaseType, VD->getDeclContext());
        RelatedDecl->print(Printer, PO);
      } else {
        llvm::SmallString<128> Buf;
        {
          llvm::raw_svector_ostream OSBuf(Buf);
          SwiftLangSupport::printDisplayName(RelatedDecl, OSBuf);
        }
        llvm::markup::appendWithXMLEscaping(OS, Buf);
      }
      OS<<"</RelatedName>";
    }
    unsigned RelatedDeclEnd = SS.size();
    RelDeclOffs.push_back(std::make_pair(RelatedDeclBegin, RelatedDeclEnd));
  });

  ASTContext &Ctx = VD->getASTContext();

  ClangImporter *Importer = static_cast<ClangImporter*>(
      Ctx.getClangModuleLoader());
  std::string ModuleName;
  auto ClangNode = VD->getClangNode();
  if (ClangNode) {
    auto ClangMod = Importer->getClangOwningModule(ClangNode);
    ModuleName = ClangMod->getFullModuleName();
  } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) {
    ModuleName = VD->getModuleContext()->getName().str();
  }
  StringRef ModuleInterfaceName;
  if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok))
    ModuleInterfaceName = IFaceGenRef->getDocumentName();

  UIdent Kind = SwiftLangSupport::getUIDForDecl(VD, IsRef);
  StringRef Name = StringRef(SS.begin()+NameBegin, NameEnd-NameBegin);
  StringRef USR = StringRef(SS.begin()+USRBegin, USREnd-USRBegin);
  StringRef TypeName = StringRef(SS.begin()+TypenameBegin,
                                 TypenameEnd-TypenameBegin);
  StringRef DocComment = StringRef(SS.begin()+DocCommentBegin,
                                   DocCommentEnd-DocCommentBegin);
  StringRef AnnotatedDecl = StringRef(SS.begin()+DeclBegin,
                                      DeclEnd-DeclBegin);

  llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc;
  StringRef Filename;
  getLocationInfo(VD, DeclarationLoc, Filename);
  if (DeclarationLoc.hasValue()) {
    DeclarationLoc = tryRemappingLocToLatestSnapshot(Lang,
                                                     *DeclarationLoc,
                                                     Filename,
                                                     PreviousASTSnaps);
    if (!DeclarationLoc.hasValue())
      return true; // failed to remap.
  }

  SmallVector<StringRef, 4> OverUSRs;
  for (auto Offs : OverUSROffs) {
    OverUSRs.push_back(StringRef(SS.begin()+Offs.first,
                                 Offs.second-Offs.first));
  }

  SmallVector<StringRef, 4> AnnotatedRelatedDecls;
  for (auto Offs : RelDeclOffs) {
    AnnotatedRelatedDecls.push_back(StringRef(SS.begin() + Offs.first,
                                              Offs.second - Offs.first));
  }

  bool IsSystem = VD->getModuleContext()->isSystemModule();
  std::string TypeInterface;

  CursorInfo Info;
  Info.Kind = Kind;
  Info.Name = Name;
  Info.USR = USR;
  Info.TypeName = TypeName;
  Info.DocComment = DocComment;
  Info.AnnotatedDeclaration = AnnotatedDecl;
  Info.ModuleName = ModuleName;
  Info.ModuleInterfaceName = ModuleInterfaceName;
  Info.DeclarationLoc = DeclarationLoc;
  Info.Filename = Filename;
  Info.OverrideUSRs = OverUSRs;
  Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls;
  Info.IsSystem = IsSystem;
  Info.TypeInterface = ASTPrinter::printTypeInterface(Ty, VD->getDeclContext(),
                                                      TypeInterface) ?
    StringRef(TypeInterface) : StringRef();
  Receiver(Info);
  return false;
}
Ejemplo n.º 19
0
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
    StringRef Filename,
    HeaderSearch &HS,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    ModuleMap::KnownHeader *SuggestedModule,
    bool &InUserSpecifiedSystemFramework) const
{
  FileManager &FileMgr = HS.getFileMgr();

  // Framework names must have a '/' in the filename.
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos) return nullptr;

  // Find out if this is the home for the specified framework, by checking
  // HeaderSearch.  Possible answers are yes/no and unknown.
  HeaderSearch::FrameworkCacheEntry &CacheEntry =
    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));

  // If it is known and in some other directory, fail.
  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
    return nullptr;

  // Otherwise, construct the path to this framework dir.

  // FrameworkName = "/System/Library/Frameworks/"
  SmallString<1024> FrameworkName;
  FrameworkName += getFrameworkDir()->getName();
  if (FrameworkName.empty() || FrameworkName.back() != '/')
    FrameworkName.push_back('/');

  // FrameworkName = "/System/Library/Frameworks/Cocoa"
  StringRef ModuleName(Filename.begin(), SlashPos);
  FrameworkName += ModuleName;

  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
  FrameworkName += ".framework/";

  // If the cache entry was unresolved, populate it now.
  if (!CacheEntry.Directory) {
    HS.IncrementFrameworkLookupCount();

    // If the framework dir doesn't exist, we fail.
    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
    if (!Dir) return nullptr;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheEntry.Directory = getFrameworkDir();

    // If this is a user search directory, check if the framework has been
    // user-specified as a system framework.
    if (getDirCharacteristic() == SrcMgr::C_User) {
      SmallString<1024> SystemFrameworkMarker(FrameworkName);
      SystemFrameworkMarker += ".system_framework";
      if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
        CacheEntry.IsUserSpecifiedSystemFramework = true;
      }
    }
  }

  // Set the 'user-specified system framework' flag.
  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;

  if (RelativePath) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
  unsigned OrigSize = FrameworkName.size();

  FrameworkName += "Headers/";

  if (SearchPath) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
  }

  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
  const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
                                        /*openFile=*/!SuggestedModule);
  if (!FE) {
    // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
    const char *Private = "Private";
    FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
                         Private+strlen(Private));
    if (SearchPath)
      SearchPath->insert(SearchPath->begin()+OrigSize, Private,
                         Private+strlen(Private));

    FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule);
  }

  // If we found the header and are allowed to suggest a module, do so now.
  if (FE && SuggestedModule) {
    // Find the framework in which this header occurs.
    StringRef FrameworkPath = FE->getDir()->getName();
    bool FoundFramework = false;
    do {
      // Determine whether this directory exists.
      const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath);
      if (!Dir)
        break;

      // If this is a framework directory, then we're a subframework of this
      // framework.
      if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
        FoundFramework = true;
        break;
      }

      // Get the parent directory name.
      FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
      if (FrameworkPath.empty())
        break;
    } while (true);

    if (FoundFramework) {
      // Find the top-level framework based on this framework.
      SmallVector<std::string, 4> SubmodulePath;
      const DirectoryEntry *TopFrameworkDir
        = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath);

      // Determine the name of the top-level framework.
      StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());

      // Load this framework module. If that succeeds, find the suggested module
      // for this header, if any.
      bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
      if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
        *SuggestedModule = HS.findModuleForHeader(FE);
      }
    } else {
      *SuggestedModule = HS.findModuleForHeader(FE);
    }
  }
  return FE;
}
Ejemplo n.º 20
0
/// GetSymbolFromOperand - Lower an MO_GlobalAddress or MO_ExternalSymbol
/// operand to an MCSymbol.
MCSymbol *X86MCInstLower::
GetSymbolFromOperand(const MachineOperand &MO) const {
  assert((MO.isGlobal() || MO.isSymbol()) && "Isn't a symbol reference");

  SmallString<128> Name;

  if (!MO.isGlobal()) {
    assert(MO.isSymbol());
    Name += MAI.getGlobalPrefix();
    Name += MO.getSymbolName();
  } else {
    const GlobalValue *GV = MO.getGlobal();
    bool isImplicitlyPrivate = false;
    if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB ||
        MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
        MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
        MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
      isImplicitlyPrivate = true;

    Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
  }

  // If the target flags on the operand changes the name of the symbol, do that
  // before we return the symbol.
  switch (MO.getTargetFlags()) {
  default: break;
  case X86II::MO_DLLIMPORT: {
    // Handle dllimport linkage.
    const char *Prefix = "__imp_";
    Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix));
    break;
  }
  case X86II::MO_DARWIN_NONLAZY:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE: {
    Name += "$non_lazy_ptr";
    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());

    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI().getGVStubEntry(Sym);
    if (StubSym.getPointer() == 0) {
      assert(MO.isGlobal() && "Extern symbol not handled yet");
      StubSym =
        MachineModuleInfoImpl::
        StubValueTy(Mang->getSymbol(MO.getGlobal()),
                    !MO.getGlobal()->hasInternalLinkage());
    }
    return Sym;
  }
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
    Name += "$non_lazy_ptr";
    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI().getHiddenGVStubEntry(Sym);
    if (StubSym.getPointer() == 0) {
      assert(MO.isGlobal() && "Extern symbol not handled yet");
      StubSym =
        MachineModuleInfoImpl::
        StubValueTy(Mang->getSymbol(MO.getGlobal()),
                    !MO.getGlobal()->hasInternalLinkage());
    }
    return Sym;
  }
  case X86II::MO_DARWIN_STUB: {
    Name += "$stub";
    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI().getFnStubEntry(Sym);
    if (StubSym.getPointer())
      return Sym;

    if (MO.isGlobal()) {
      StubSym =
        MachineModuleInfoImpl::
        StubValueTy(Mang->getSymbol(MO.getGlobal()),
                    !MO.getGlobal()->hasInternalLinkage());
    } else {
      Name.erase(Name.end()-5, Name.end());
      StubSym =
        MachineModuleInfoImpl::
        StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false);
    }
    return Sym;
  }
  }

  return Ctx.GetOrCreateSymbol(Name.str());
}
Ejemplo n.º 21
0
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
    StringRef Filename,
    HeaderSearch &HS,
    SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath,
    Module **SuggestedModule,
    bool &InUserSpecifiedSystemFramework) const
{
  FileManager &FileMgr = HS.getFileMgr();

  // Framework names must have a '/' in the filename.
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos) return 0;

  // Find out if this is the home for the specified framework, by checking
  // HeaderSearch.  Possible answers are yes/no and unknown.
  HeaderSearch::FrameworkCacheEntry &CacheEntry =
    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));

  // If it is known and in some other directory, fail.
  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
    return 0;

  // Otherwise, construct the path to this framework dir.

  // FrameworkName = "/System/Library/Frameworks/"
  SmallString<1024> FrameworkName;
  FrameworkName += getFrameworkDir()->getName();
  if (FrameworkName.empty() || FrameworkName.back() != '/')
    FrameworkName.push_back('/');

  // FrameworkName = "/System/Library/Frameworks/Cocoa"
  StringRef ModuleName(Filename.begin(), SlashPos);
  FrameworkName += ModuleName;

  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
  FrameworkName += ".framework/";

  // If the cache entry was unresolved, populate it now.
  if (CacheEntry.Directory == 0) {
    HS.IncrementFrameworkLookupCount();

    // If the framework dir doesn't exist, we fail.
    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
    if (Dir == 0) return 0;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheEntry.Directory = getFrameworkDir();

    // If this is a user search directory, check if the framework has been
    // user-specified as a system framework.
    if (getDirCharacteristic() == SrcMgr::C_User) {
      SmallString<1024> SystemFrameworkMarker(FrameworkName);
      SystemFrameworkMarker += ".system_framework";
      if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
        CacheEntry.IsUserSpecifiedSystemFramework = true;
      }
    }
  }

  // Set the 'user-specified system framework' flag.
  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;

  if (RelativePath != NULL) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // If we're allowed to look for modules, try to load or create the module
  // corresponding to this framework.
  Module *Module = 0;
  if (SuggestedModule) {
    if (const DirectoryEntry *FrameworkDir
                                        = FileMgr.getDirectory(FrameworkName)) {
      bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
      Module = HS.loadFrameworkModule(ModuleName, FrameworkDir, IsSystem);
    }
  }
  
  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
  unsigned OrigSize = FrameworkName.size();

  FrameworkName += "Headers/";

  if (SearchPath != NULL) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
  }

  // Determine whether this is the module we're building or not.
  bool AutomaticImport = Module;  
  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
  if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
                                            /*openFile=*/!AutomaticImport)) {
    if (AutomaticImport)
      *SuggestedModule = HS.findModuleForHeader(FE);
    return FE;
  }

  // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
  const char *Private = "Private";
  FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
                       Private+strlen(Private));
  if (SearchPath != NULL)
    SearchPath->insert(SearchPath->begin()+OrigSize, Private,
                       Private+strlen(Private));

  const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 
                                        /*openFile=*/!AutomaticImport);
  if (FE && AutomaticImport)
    *SuggestedModule = HS.findModuleForHeader(FE);
  return FE;
}
Ejemplo n.º 22
0
/// parseTypeIdentifierOrTypeComposition
/// - Identifiers and compositions both start with the same identifier
///   token, parse it and continue constructing a composition if the
///   next token is '&'
///
///   type-composition:
///     type-identifier ('&' type-identifier)*
///     'protocol' '<' type-composition-list-deprecated? '>'
///
///   type-composition-list-deprecated:
///     type-identifier (',' type-identifier)*
ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
  
  // Handle deprecated case
  if (Tok.getKind() == tok::kw_protocol && startsWithLess(peekToken())) {
    SourceLoc ProtocolLoc = consumeToken(tok::kw_protocol);
    SourceLoc LAngleLoc = consumeStartingLess();
    
    // Parse the type-composition-list.
    ParserStatus Status;
    SmallVector<IdentTypeRepr *, 4> Protocols;
    bool IsEmpty = startsWithGreater(Tok);
    if (!IsEmpty) {
      do {
        // Parse the type-identifier.
        ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
        Status |= Protocol;
        if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(
                                                       Protocol.getPtrOrNull()))
          Protocols.push_back(ident);
      } while (consumeIf(tok::comma));
    }

    // Check for the terminating '>'.
    SourceLoc RAngleLoc = PreviousLoc;
    if (startsWithGreater(Tok)) {
      RAngleLoc = consumeStartingGreater();
    } else {
      if (Status.isSuccess()) {
        diagnose(Tok, diag::expected_rangle_protocol);
        diagnose(LAngleLoc, diag::opening_angle);
        Status.setIsParseError();
      }
      
      // Skip until we hit the '>'.
      RAngleLoc = skipUntilGreaterInTypeList(/*protocolComposition=*/true);
    }

    auto composition = ProtocolCompositionTypeRepr::create(
      Context, Protocols, ProtocolLoc, {LAngleLoc, RAngleLoc});

    if (Status.isSuccess()) {
      // Only if we have complete protocol<...> construct, diagnose deprecated.

      SmallString<32> replacement;
      if (Protocols.empty()) {
        replacement = "Any";
      } else {
        auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
          auto SourceRange = Ty->getSourceRange();
          return SourceMgr.extractText(
            Lexer::getCharSourceRangeFromSourceRange(SourceMgr, SourceRange));
        };
        auto Begin = Protocols.begin();
        replacement += extractText(*Begin);
        while (++Begin != Protocols.end()) {
          replacement += " & ";
          replacement += extractText(*Begin);
        }
      }

      // Copy trailing content after '>' to the replacement string.
      // FIXME: lexer should smartly separate '>' and trailing contents like '?'.
      StringRef TrailingContent = L->getTokenAt(RAngleLoc).getRange().str().
        substr(1);
      if (!TrailingContent.empty()) {
        if (Protocols.size() > 1) {
          replacement.insert(replacement.begin(), '(');
          replacement += ")";
        }
        replacement += TrailingContent;
      }

      // Replace 'protocol<T1, T2>' with 'T1 & T2'
      diagnose(ProtocolLoc,
        IsEmpty              ? diag::deprecated_any_composition :
        Protocols.size() > 1 ? diag::deprecated_protocol_composition :
                               diag::deprecated_protocol_composition_single)
        .highlight(composition->getSourceRange())
        .fixItReplace(composition->getSourceRange(), replacement);
    }

    return makeParserResult(Status, composition);
  }
  
  SourceLoc FirstTypeLoc = Tok.getLoc();
  
  // Parse the first type
  ParserResult<TypeRepr> FirstType = parseTypeIdentifier();
  if (!Tok.isContextualPunctuator("&"))
    return FirstType;
  
  SmallVector<IdentTypeRepr *, 4> Protocols;
  ParserStatus Status;

  // If it is not 'Any', add it to the protocol list
  if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(FirstType.getPtrOrNull()))
    Protocols.push_back(ident);
  Status |= FirstType;
  auto FirstAmpersandLoc = Tok.getLoc();
  
  while (Tok.isContextualPunctuator("&")) {
    consumeToken(); // consume '&'
    ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
    Status |= Protocol;
    if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull()))
      Protocols.push_back(ident);
  };
  
  return makeParserResult(Status, ProtocolCompositionTypeRepr::create(
    Context, Protocols, FirstTypeLoc, {FirstAmpersandLoc, PreviousLoc}));
}