Esempio n. 1
0
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
  DeclContext *PrimaryContext = getPrimaryContext();
  if (PrimaryContext != this)
    return PrimaryContext->lookup(Name);

  if (hasExternalVisibleStorage()) {
    // Check to see if we've already cached the lookup results.
    if (LookupPtr) {
      StoredDeclsMap::iterator I = LookupPtr->find(Name);
      if (I != LookupPtr->end())
        return I->second.getLookupResult(getParentASTContext());
    }

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    return Source->FindExternalVisibleDeclsByName(this, Name);
  }

  /// If there is no lookup data structure, build one now by walking
  /// all of the linked DeclContexts (in declaration order!) and
  /// inserting their values.
  if (!LookupPtr) {
    buildLookup(this);

    if (!LookupPtr)
      return lookup_result(lookup_iterator(0), lookup_iterator(0));
  }

  StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
  if (Pos == LookupPtr->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));
  return Pos->second.getLookupResult(getParentASTContext());
}
Esempio n. 2
0
/// \brief Load the declarations within this lexical storage from an
/// external source.
void
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  assert(hasExternalLexicalStorage() && Source && "No external storage?");

  // Notify that we have a DeclContext that is initializing.
  ExternalASTSource::Deserializing ADeclContext(Source);

  llvm::SmallVector<Decl*, 64> Decls;
  if (Source->FindExternalLexicalDecls(this, Decls))
    return;

  // There is no longer any lexical storage in this context
  ExternalLexicalStorage = false;

  if (Decls.empty())
    return;

  // We may have already loaded just the fields of this record, in which case
  // don't add the decls, just replace the FirstDecl/LastDecl chain.
  if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
    if (RD->LoadedFieldsFromExternalStorage) {
      llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
      return;
    }

  // Splice the newly-read declarations into the beginning of the list
  // of declarations.
  Decl *ExternalFirst, *ExternalLast;
  llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls);
  ExternalLast->NextDeclInContext = FirstDecl;
  FirstDecl = ExternalFirst;
  if (!LastDecl)
    LastDecl = ExternalLast;
}
Esempio n. 3
0
void DefnContext::MaterializeVisibleDefnsFromExternalStorage() {
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  assert(hasExternalVisibleStorage() && Source && "No external storage?");

  if (!LookupPtr)
    CreateStoredDefnsMap(getParentASTContext());
  Source->MaterializeVisibleDefns(this);
}
Esempio n. 4
0
/// \brief We have just acquired external visible storage, and we already have
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() {
  assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer());
  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);
  }
}
Esempio n. 5
0
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
  assert(DeclKind != Decl::LinkageSpec &&
         "Should not perform lookups into linkage specs!");

  DeclContext *PrimaryContext = getPrimaryContext();
  if (PrimaryContext != this)
    return PrimaryContext->lookup(Name);

  if (hasExternalVisibleStorage()) {
    StoredDeclsMap *Map = LookupPtr.getPointer();
    if (LookupPtr.getInt())
      Map = buildLookup();
    else if (NeedToReconcileExternalVisibleStorage)
      reconcileExternalVisibleStorage();

    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.
    std::pair<StoredDeclsMap::iterator, bool> R =
        Map->insert(std::make_pair(Name, StoredDeclsList()));
    if (!R.second)
      return R.first->second.getLookupResult();

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    if (Source->FindExternalVisibleDeclsByName(this, Name)) {
      if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
        StoredDeclsMap::iterator I = Map->find(Name);
        if (I != Map->end())
          return I->second.getLookupResult();
      }
    }

    return lookup_result(lookup_iterator(0), lookup_iterator(0));
  }

  StoredDeclsMap *Map = LookupPtr.getPointer();
  if (LookupPtr.getInt())
    Map = buildLookup();

  if (!Map)
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  StoredDeclsMap::iterator I = Map->find(Name);
  if (I == Map->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  return I->second.getLookupResult();
}
Esempio n. 6
0
DefnContext::lookup_result
DefnContext::lookup(DefinitionName Name) {
  if (hasExternalVisibleStorage()) {
    // Check to see if we've already cached the lookup results.
    if (LookupPtr) {
      StoredDefnsMap::iterator I = LookupPtr->find(Name);
      if (I != LookupPtr->end())
        return I->second.getLookupResult();
    }

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    return Source->FindExternalVisibleDefnsByName(this, Name);
  }

  StoredDefnsMap::iterator Pos = LookupPtr->find(Name);
  if (Pos == LookupPtr->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));
  return Pos->second.getLookupResult();
}
Esempio n. 7
0
  void IncrementalParser::Initialize() {
    if (hasCodeGenerator())
      getCodeGenerator()->Initialize(getCI()->getASTContext());

    CompilationOptions CO;
    CO.DeclarationExtraction = 0;
    CO.ValuePrinting = CompilationOptions::VPDisabled;
    CO.CodeGeneration = hasCodeGenerator();

    // pull in PCHs
    const std::string& PCHFileName
      = m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude;
    if (!PCHFileName.empty()) {
      
      Transaction* CurT = beginTransaction(CO);
      m_CI->createPCHExternalASTSource(PCHFileName,
                                       true /*DisablePCHValidation*/,
                                       true /*AllowPCHWithCompilerErrors*/,
                                       0 /*DeserializationListener*/);
      Transaction* EndedT = endTransaction(CurT);
      commitTransaction(EndedT);
    }

    Transaction* CurT = beginTransaction(CO);
    Sema* TheSema = &m_CI->getSema();
    m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema,
                              false /*skipFuncBodies*/));
    m_CI->getPreprocessor().EnterMainSourceFile();
    // Initialize the parser after we have entered the main source file.
    m_Parser->Initialize();
    // Perform initialization that occurs after the parser has been initialized
    // but before it parses anything. Initializes the consumers too.
    TheSema->Initialize();

    ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
    if (External)
      External->StartTranslationUnit(m_Consumer);

    Transaction* EndedT = endTransaction(CurT);
    commitTransaction(EndedT);
  }
Esempio n. 8
0
/// \brief Load the declarations within this lexical storage from an
/// external source.
void
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  assert(hasExternalLexicalStorage() && Source && "No external storage?");

  // Notify that we have a DeclContext that is initializing.
  ExternalASTSource::Deserializing ADeclContext(Source);

  llvm::SmallVector<Decl*, 64> Decls;
  if (Source->FindExternalLexicalDecls(this, Decls))
    return;

  // There is no longer any lexical storage in this context
  ExternalLexicalStorage = false;

  if (Decls.empty())
    return;

  // Resolve all of the declaration IDs into declarations, building up
  // a chain of declarations via the Decl::NextDeclInContext field.
  Decl *FirstNewDecl = 0;
  Decl *PrevDecl = 0;
  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
    Decl *D = Decls[I];
    if (PrevDecl)
      PrevDecl->NextDeclInContext = D;
    else
      FirstNewDecl = D;

    PrevDecl = D;
  }

  // Splice the newly-read declarations into the beginning of the list
  // of declarations.
  PrevDecl->NextDeclInContext = FirstDecl;
  FirstDecl = FirstNewDecl;
  if (!LastDecl)
    LastDecl = PrevDecl;
}
Esempio n. 9
0
void
DeclContext::LoadVisibleDeclsFromExternalStorage() const {
  DeclContext *This = const_cast<DeclContext *>(this);
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  assert(hasExternalVisibleStorage() && Source && "No external storage?");

  llvm::SmallVector<VisibleDeclaration, 64> Decls;
  if (Source->ReadDeclsVisibleInContext(This, Decls))
    return;

  // There is no longer any visible storage in this context
  ExternalVisibleStorage = false;

  // Load the declaration IDs for all of the names visible in this
  // context.
  assert(!LookupPtr && "Have a lookup map before de-serialization?");
  StoredDeclsMap *Map = new StoredDeclsMap;
  LookupPtr = Map;
  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
    (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
  }
}
Esempio n. 10
0
/// \brief Load the declarations within this lexical storage from an
/// external source.
void
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  assert(hasExternalLexicalStorage() && Source && "No external storage?");

  // Notify that we have a DeclContext that is initializing.
  ExternalASTSource::Deserializing ADeclContext(Source);
  
  // Load the external declarations, if any.
  SmallVector<Decl*, 64> Decls;
  ExternalLexicalStorage = false;
  switch (Source->FindExternalLexicalDecls(this, Decls)) {
  case ELR_Success:
    break;
    
  case ELR_Failure:
  case ELR_AlreadyLoaded:
    return;
  }

  if (Decls.empty())
    return;

  // We may have already loaded just the fields of this record, in which case
  // we need to ignore them.
  bool FieldsAlreadyLoaded = false;
  if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
    FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage;
  
  // Splice the newly-read declarations into the beginning of the list
  // of declarations.
  Decl *ExternalFirst, *ExternalLast;
  llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls,
                                                          FieldsAlreadyLoaded);
  ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
  FirstDecl = ExternalFirst;
  if (!LastDecl)
    LastDecl = ExternalLast;
}
Esempio n. 11
0
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
  assert(DeclKind != Decl::LinkageSpec &&
         "Should not perform lookups into linkage specs!");

  DeclContext *PrimaryContext = getPrimaryContext();
  if (PrimaryContext != this)
    return PrimaryContext->lookup(Name);

  if (hasExternalVisibleStorage()) {
    // If a PCH has a result for this name, and we have a local declaration, we
    // will have imported the PCH result when adding the local declaration.
    // FIXME: For modules, we could have had more declarations added by module
    // imoprts since we saw the declaration of the local name.
    if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
      StoredDeclsMap::iterator I = Map->find(Name);
      if (I != Map->end())
        return I->second.getLookupResult();
    }

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    return Source->FindExternalVisibleDeclsByName(this, Name);
  }

  StoredDeclsMap *Map = LookupPtr.getPointer();
  if (LookupPtr.getInt())
    Map = buildLookup();

  if (!Map)
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  StoredDeclsMap::iterator I = Map->find(Name);
  if (I == Map->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  return I->second.getLookupResult();
}
Esempio n. 12
0
DeclContext::lookup_result
DeclContext::lookup(IdentifierInfo &Name) {
  DeclContext *PrimaryContext = getPrimaryContext();
  if (PrimaryContext != this)  // FIXME: not needed?
    return PrimaryContext->lookup(Name);

#if 0  // FIXME: modules. eventually. resync this part from clang.
  if (hasExternalVisibleStorage()) {
    // If a PCH has a result for this name, and we have a local declaration, we
    // will have imported the PCH result when adding the local declaration.
    // FIXME: For modules, we could have had more declarations added by module
    // imoprts since we saw the declaration of the local name.
    if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
      StoredDeclsMap::iterator I = Map->find(&Name);
      if (I != Map->end())
        return I->second.getLookupResult();
    }

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    return Source->FindExternalVisibleDeclsByName(this, Name);
  }
#endif

  StoredDeclsMap *Map = LookupPtr.getPointer();
  if (LookupPtr.getInt())
    Map = buildLookup();

  if (!Map)
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  StoredDeclsMap::iterator I = Map->find(&Name);
  if (I == Map->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  return I->second.getLookupResult();
}
Esempio n. 13
0
void StoredDeclsList::materializeDecls(ASTContext &Context) {
  if (isNull())
    return;

  switch ((DataKind)(Data & 0x03)) {
  case DK_Decl:
  case DK_Decl_Vector:
    break;

  case DK_DeclID: {
    // Resolve this declaration ID to an actual declaration by
    // querying the external AST source.
    unsigned DeclID = Data >> 2;

    ExternalASTSource *Source = Context.getExternalSource();
    assert(Source && "No external AST source available!");

    Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
    break;
  }

  case DK_ID_Vector: {
    // We have a vector of declaration IDs. Resolve all of them to
    // actual declarations.
    VectorTy &Vector = *getAsVector();
    ExternalASTSource *Source = Context.getExternalSource();
    assert(Source && "No external AST source available!");

    for (unsigned I = 0, N = Vector.size(); I != N; ++I)
      Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));

    Data = (Data & ~0x03) | DK_Decl_Vector;
    break;
  }
  }
}
Esempio n. 14
0
  bool
  IncrementalParser::Initialize(llvm::SmallVectorImpl<ParseResultTransaction>&
                                result, bool isChildInterpreter) {
    m_TransactionPool.reset(new TransactionPool);
    if (hasCodeGenerator())
      getCodeGenerator()->Initialize(getCI()->getASTContext());

    CompilationOptions CO = m_Interpreter->makeDefaultCompilationOpts();
    Transaction* CurT = beginTransaction(CO);
    Preprocessor& PP = m_CI->getPreprocessor();
    DiagnosticsEngine& Diags = m_CI->getSema().getDiagnostics();

    // Pull in PCH.
    const std::string& PCHFileName
      = m_CI->getInvocation().getPreprocessorOpts().ImplicitPCHInclude;
    if (!PCHFileName.empty()) {
      Transaction* PchT = beginTransaction(CO);
      DiagnosticErrorTrap Trap(Diags);
      m_CI->createPCHExternalASTSource(PCHFileName,
                                       true /*DisablePCHValidation*/,
                                       true /*AllowPCHWithCompilerErrors*/,
                                       0 /*DeserializationListener*/,
                                       true /*OwnsDeserializationListener*/);
      result.push_back(endTransaction(PchT));
      if (Trap.hasErrorOccurred()) {
        result.push_back(endTransaction(CurT));
        return false;
      }
    }

    addClingPragmas(*m_Interpreter);

    // Must happen after attaching the PCH, else PCH elements will end up
    // being lexed.
    PP.EnterMainSourceFile();

    Sema* TheSema = &m_CI->getSema();
    m_Parser.reset(new Parser(PP, *TheSema, false /*skipFuncBodies*/));

    // Initialize the parser after PP has entered the main source file.
    m_Parser->Initialize();

    ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
    if (External)
      External->StartTranslationUnit(m_Consumer);

    // Start parsing the "main file" to warm up lexing (enter caching lex mode
    // for ParseInternal()'s call EnterSourceFile() to make sense.
    while (!m_Parser->ParseTopLevelDecl()) {}

    // If I belong to the parent Interpreter, am using C++, and -noruntime
    // wasn't given on command line, then #include <new> and check ABI
    if (!isChildInterpreter && m_CI->getLangOpts().CPlusPlus &&
        !m_Interpreter->getOptions().NoRuntime) {
      // <new> is needed by the ValuePrinter so it's a good thing to include it.
      // We need to include it to determine the version number of the standard
      // library implementation.
      ParseInternal("#include <new>");
      // That's really C++ ABI compatibility. C has other problems ;-)
      CheckABICompatibility(*m_Interpreter);
    }

    // DO NOT commit the transactions here: static initialization in these
    // transactions requires gCling through local_cxa_atexit(), but that has not
    // been defined yet!
    ParseResultTransaction PRT = endTransaction(CurT);
    result.push_back(PRT);
    return true;
  }
Esempio n. 15
0
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
  assert(DeclKind != Decl::LinkageSpec &&
         "Should not perform lookups into linkage specs!");

  DeclContext *PrimaryContext = getPrimaryContext();
  if (PrimaryContext != this)
    return PrimaryContext->lookup(Name);

#if AXEL_LOOKUP_CHANGES
  StoredDeclsMap *Map = LookupPtr.getPointer();
  if (LookupPtr.getInt())
    Map = buildLookup();
#endif

  if (hasExternalVisibleStorage()) {
    // If a PCH has a result for this name, and we have a local declaration, we
    // will have imported the PCH result when adding the local declaration.
    // FIXME: For modules, we could have had more declarations added by module
    // imoprts since we saw the declaration of the local name.
#if AXEL_LOOKUP_CHANGES
    if (Map) {
#else
    if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
#endif
      StoredDeclsMap::iterator I = Map->find(Name);
      if (I != Map->end())
        return I->second.getLookupResult();
    }

    ExternalASTSource *Source = getParentASTContext().getExternalSource();
    return Source->FindExternalVisibleDeclsByName(this, Name);
  }

#ifndef AXEL_LOOKUP_CHANGES
  StoredDeclsMap *Map = LookupPtr.getPointer();
  if (LookupPtr.getInt())
    Map = buildLookup();
#endif

  if (!Map)
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  StoredDeclsMap::iterator I = Map->find(Name);
  if (I == Map->end())
    return lookup_result(lookup_iterator(0), lookup_iterator(0));

  return I->second.getLookupResult();
}

void DeclContext::localUncachedLookup(DeclarationName Name, 
                                  llvm::SmallVectorImpl<NamedDecl *> &Results) {
  Results.clear();
  
  // If there's no external storage, just perform a normal lookup and copy
  // the results.
  if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) {
    lookup_result LookupResults = lookup(Name);
    Results.insert(Results.end(), LookupResults.first, LookupResults.second);
    return;
  }

  // If we have a lookup table, check there first. Maybe we'll get lucky.
  if (Name) {
    if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
      StoredDeclsMap::iterator Pos = Map->find(Name);
      if (Pos != Map->end()) {
        Results.insert(Results.end(),
                       Pos->second.getLookupResult().first,
                       Pos->second.getLookupResult().second);
        return;
      }
    }
  }

  // Slow case: grovel through the declarations in our chain looking for 
  // matches.
  for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
    if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
      if (ND->getDeclName() == Name)
        Results.push_back(ND);
  }
}
Esempio n. 16
0
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::EnableStatistics();
    Stmt::EnableStatistics();
  }

  // Also turn on collection of stats inside of the Sema object.
  bool OldCollectStats = PrintStats;
  std::swap(OldCollectStats, S.CollectStats);

  // Initialize the template instantiation observer chain.
  // FIXME: See note on "finalize" below.
  initialize(S.TemplateInstCallbacks, S);

  ASTConsumer *Consumer = &S.getASTConsumer();

  std::unique_ptr<Parser> ParseOP(
      new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
  Parser &P = *ParseOP.get();

  llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup>
      CleanupPrettyStack(llvm::SavePrettyStackState());
  PrettyStackTraceParserEntry CrashInfo(P);

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Parser>
    CleanupParser(ParseOP.get());

  S.getPreprocessor().EnterMainSourceFile();
  P.Initialize();

  Parser::DeclGroupPtrTy ADecl;
  ExternalASTSource *External = S.getASTContext().getExternalSource();
  if (External)
    External->StartTranslationUnit(Consumer);

  for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
       AtEOF = P.ParseTopLevelDecl(ADecl)) {
    // If we got a null return and something *was* parsed, ignore it.  This
    // is due to a top-level semicolon, an action override, or a parse error
    // skipping something.
    if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
      return;
  }

  // Process any TopLevelDecls generated by #pragma weak.
  for (Decl *D : S.WeakTopLevelDecls())
    Consumer->HandleTopLevelDecl(DeclGroupRef(D));
  
  Consumer->HandleTranslationUnit(S.getASTContext());

  // Finalize the template instantiation observer chain.
  // FIXME: This (and init.) should be done in the Sema class, but because
  // Sema does not have a reliable "Finalize" function (it has a
  // destructor, but it is not guaranteed to be called ("-disable-free")).
  // So, do the initialization above and do the finalization here:
  finalize(S.TemplateInstCallbacks, S);

  std::swap(OldCollectStats, S.CollectStats);
  if (PrintStats) {
    llvm::errs() << "\nSTATISTICS:\n";
    P.getActions().PrintStats();
    S.getASTContext().PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();
  }
}
Esempio n. 17
0
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::EnableStatistics();
    Stmt::EnableStatistics();
  }

  // Also turn on collection of stats inside of the Sema object.
  bool OldCollectStats = PrintStats;
  std::swap(OldCollectStats, S.CollectStats);

  ASTConsumer *Consumer = &S.getASTConsumer();

  OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
                                       SkipFunctionBodies));
  Parser &P = *ParseOP.get();

  PrettyStackTraceParserEntry CrashInfo(P);

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Parser>
    CleanupParser(ParseOP.get());

  S.getPreprocessor().EnterMainSourceFile();
  P.Initialize();
  S.Initialize();

  // C11 6.9p1 says translation units must have at least one top-level
  // declaration. C++ doesn't have this restriction. We also don't want to
  // complain if we have a precompiled header, although technically if the PCH
  // is empty we should still emit the (pedantic) diagnostic.
  Parser::DeclGroupPtrTy ADecl;
  ExternalASTSource *External = S.getASTContext().getExternalSource();
  if (External)
    External->StartTranslationUnit(Consumer);

  if (P.ParseTopLevelDecl(ADecl)) {
    if (!External && !S.getLangOpts().CPlusPlus)
      P.Diag(diag::ext_empty_translation_unit);
  } else {
    do {
      // If we got a null return and something *was* parsed, ignore it.  This
      // is due to a top-level semicolon, an action override, or a parse error
      // skipping something.
      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
	return;
    } while (!P.ParseTopLevelDecl(ADecl));
  }

  // Process any TopLevelDecls generated by #pragma weak.
  for (SmallVector<Decl*,2>::iterator
       I = S.WeakTopLevelDecls().begin(),
       E = S.WeakTopLevelDecls().end(); I != E; ++I)
    Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
  
  Consumer->HandleTranslationUnit(S.getASTContext());

  std::swap(OldCollectStats, S.CollectStats);
  if (PrintStats) {
    llvm::errs() << "\nSTATISTICS:\n";
    P.getActions().PrintStats();
    S.getASTContext().PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();
  }
}