[clang][Syntax] syntax::Arena doesnt own TokenBuffer

Currently an Arena can only be built while consuming a TokenBuffer,
some users (like clangd) might want to share a TokenBuffer with multiple
compenents. This patch changes Arena's TokenBuffer member to be a reference so
that it can be created with read-only token buffers.

Differential Revision: https://reviews.llvm.org/D84973
This commit is contained in:
Kadir Cetinkaya 2020-07-30 21:38:40 +02:00
parent fb5588b0ad
commit 1618828165
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
3 changed files with 18 additions and 11 deletions

View File

@ -39,7 +39,7 @@ namespace syntax {
class Arena {
public:
Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
TokenBuffer Tokens);
const TokenBuffer &Tokens);
const SourceManager &sourceManager() const { return SourceMgr; }
const LangOptions &langOptions() const { return LangOpts; }
@ -56,7 +56,7 @@ public:
private:
SourceManager &SourceMgr;
const LangOptions &LangOpts;
TokenBuffer Tokens;
const TokenBuffer &Tokens;
/// IDs and storage for additional tokenized files.
llvm::DenseMap<FileID, std::vector<syntax::Token>> ExtraTokens;
/// Keeps all the allocated nodes and their intermediate data structures.

View File

@ -33,8 +33,8 @@ static void traverse(syntax::Node *N,
} // namespace
syntax::Arena::Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
TokenBuffer Tokens)
: SourceMgr(SourceMgr), LangOpts(LangOpts), Tokens(std::move(Tokens)) {}
const TokenBuffer &Tokens)
: SourceMgr(SourceMgr), LangOpts(LangOpts), Tokens(Tokens) {}
const clang::syntax::TokenBuffer &syntax::Arena::tokenBuffer() const {
return Tokens;

View File

@ -35,6 +35,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <cstdlib>
#include <memory>
using namespace clang;
@ -59,22 +60,25 @@ protected:
class BuildSyntaxTree : public ASTConsumer {
public:
BuildSyntaxTree(syntax::TranslationUnit *&Root,
std::unique_ptr<syntax::TokenBuffer> &TB,
std::unique_ptr<syntax::Arena> &Arena,
std::unique_ptr<syntax::TokenCollector> Tokens)
: Root(Root), Arena(Arena), Tokens(std::move(Tokens)) {
: Root(Root), TB(TB), Arena(Arena), Tokens(std::move(Tokens)) {
assert(this->Tokens);
}
void HandleTranslationUnit(ASTContext &Ctx) override {
Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
Ctx.getLangOpts(),
std::move(*Tokens).consume());
TB =
std::make_unique<syntax::TokenBuffer>(std::move(*Tokens).consume());
Tokens = nullptr; // make sure we fail if this gets called twice.
Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
Ctx.getLangOpts(), *TB);
Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl());
}
private:
syntax::TranslationUnit *&Root;
std::unique_ptr<syntax::TokenBuffer> &TB;
std::unique_ptr<syntax::Arena> &Arena;
std::unique_ptr<syntax::TokenCollector> Tokens;
};
@ -82,20 +86,22 @@ protected:
class BuildSyntaxTreeAction : public ASTFrontendAction {
public:
BuildSyntaxTreeAction(syntax::TranslationUnit *&Root,
std::unique_ptr<syntax::TokenBuffer> &TB,
std::unique_ptr<syntax::Arena> &Arena)
: Root(Root), Arena(Arena) {}
: Root(Root), TB(TB), Arena(Arena) {}
std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
// We start recording the tokens, ast consumer will take on the result.
auto Tokens =
std::make_unique<syntax::TokenCollector>(CI.getPreprocessor());
return std::make_unique<BuildSyntaxTree>(Root, Arena,
return std::make_unique<BuildSyntaxTree>(Root, TB, Arena,
std::move(Tokens));
}
private:
syntax::TranslationUnit *&Root;
std::unique_ptr<syntax::TokenBuffer> &TB;
std::unique_ptr<syntax::Arena> &Arena;
};
@ -132,7 +138,7 @@ protected:
Compiler.setSourceManager(SourceMgr.get());
syntax::TranslationUnit *Root = nullptr;
BuildSyntaxTreeAction Recorder(Root, this->Arena);
BuildSyntaxTreeAction Recorder(Root, this->TB, this->Arena);
// Action could not be executed but the frontend didn't identify any errors
// in the code ==> problem in setting up the action.
@ -204,6 +210,7 @@ protected:
new SourceManager(*Diags, *FileMgr);
std::shared_ptr<CompilerInvocation> Invocation;
// Set after calling buildTree().
std::unique_ptr<syntax::TokenBuffer> TB;
std::unique_ptr<syntax::Arena> Arena;
};