friend class ASTWriter;
template <class> friend class serialization::AbstractTypeReader;
friend class CXXRecordDecl;
+ friend class IncrementalParser;
/// A mapping to contain the template or declaration that
/// a variable declaration describes or was instantiated from,
ImportDecl *FirstLocalImport = nullptr;
ImportDecl *LastLocalImport = nullptr;
- TranslationUnitDecl *TUDecl;
+ TranslationUnitDecl *TUDecl = nullptr;
mutable ExternCContextDecl *ExternCContext = nullptr;
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
+ const TranslationUnitKind TUKind;
mutable DeclarationNameTable DeclarationNames;
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener = nullptr;
/// Get the initializations to perform when importing a module, if any.
ArrayRef<Decl*> getModuleInitializers(Module *M);
- TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
+ TranslationUnitDecl *getTranslationUnitDecl() const {
+ return TUDecl->getMostRecentDecl();
+ }
+ void addTranslationUnitDecl() {
+ assert(!TUDecl || TUKind == TU_Incremental);
+ TranslationUnitDecl *NewTUDecl = TranslationUnitDecl::Create(*this);
+ if (TraversalScope.empty() || TraversalScope.back() == TUDecl)
+ TraversalScope = {NewTUDecl};
+ if (TUDecl)
+ NewTUDecl->setPreviousDecl(TUDecl);
+ TUDecl = NewTUDecl;
+ }
ExternCContextDecl *getExternCContextDecl() const;
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
llvm::DenseSet<const VarDecl *> CUDADeviceVarODRUsedByHost;
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
- SelectorTable &sels, Builtin::Context &builtins);
+ SelectorTable &sels, Builtin::Context &builtins,
+ TranslationUnitKind TUKind);
ASTContext(const ASTContext &) = delete;
ASTContext &operator=(const ASTContext &) = delete;
~ASTContext();
class VarTemplateDecl;
/// The top declaration context.
-class TranslationUnitDecl : public Decl, public DeclContext {
+class TranslationUnitDecl : public Decl,
+ public DeclContext,
+ public Redeclarable<TranslationUnitDecl> {
+ using redeclarable_base = Redeclarable<TranslationUnitDecl>;
+
+ TranslationUnitDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+
+ TranslationUnitDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+
+ TranslationUnitDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
ASTContext &Ctx;
/// The (most recently entered) anonymous namespace for this
virtual void anchor();
public:
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::isFirstDecl;
+ using redeclarable_base::redecls;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+
ASTContext &getASTContext() const { return Ctx; }
NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class IncrementalParser;
Redeclarable(const ASTContext &Ctx)
: RedeclLink(LatestDeclLink(Ctx)),
TU_Prefix,
/// The translation unit is a module.
- TU_Module
+ TU_Module,
+
+ /// The translation unit is a is a complete translation unit that we might
+ /// incrementally extend later.
+ TU_Incremental
};
} // namespace clang
#ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
#define LLVM_CLANG_INTERPRETER_INTERPRETER_H
-#include "clang/Interpreter/Transaction.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
#include "llvm/Support/Error.h"
static llvm::Expected<std::unique_ptr<Interpreter>>
create(std::unique_ptr<CompilerInstance> CI);
const CompilerInstance *getCompilerInstance() const;
- llvm::Expected<Transaction &> Parse(llvm::StringRef Code);
- llvm::Error Execute(Transaction &T);
+ llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
+ llvm::Error Execute(PartialTranslationUnit &T);
llvm::Error ParseAndExecute(llvm::StringRef Code) {
- auto ErrOrTransaction = Parse(Code);
- if (auto Err = ErrOrTransaction.takeError())
- return Err;
- if (ErrOrTransaction->TheModule)
- return Execute(*ErrOrTransaction);
+ auto PTU = Parse(Code);
+ if (!PTU)
+ return PTU.takeError();
+ if (PTU->TheModule)
+ return Execute(*PTU);
return llvm::Error::success();
}
};
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_INTERPRETER_TRANSACTION_H
-#define LLVM_CLANG_INTERPRETER_TRANSACTION_H
+#ifndef LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H
+#define LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H
#include <memory>
-#include <vector>
namespace llvm {
class Module;
namespace clang {
-class DeclGroupRef;
+class TranslationUnitDecl;
/// The class keeps track of various objects created as part of processing
/// incremental inputs.
-struct Transaction {
- /// The decls created for the input.
- std::vector<clang::DeclGroupRef> Decls;
+struct PartialTranslationUnit {
+ TranslationUnitDecl *TUPart = nullptr;
/// The llvm IR produced for the input.
std::unique_ptr<llvm::Module> TheModule;
};
} // namespace clang
-#endif // LLVM_CLANG_INTERPRETER_TRANSACTION_H
+#endif // LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H
/// avoid tearing the Lexer and etc. down).
bool IncrementalProcessing = false;
+public:
/// The kind of translation unit we are processing.
- TranslationUnitKind TUKind;
+ const TranslationUnitKind TUKind;
+private:
/// The code-completion handler.
CodeCompletionHandler *CodeComplete = nullptr;
/// initializers for tentative definitions in C) once parsing has
/// completed. Modules and precompiled headers perform different kinds of
/// checks.
- TranslationUnitKind TUKind;
+ const TranslationUnitKind TUKind;
llvm::BumpPtrAllocator BumpAlloc;
ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
IdentifierTable &idents, SelectorTable &sels,
- Builtin::Context &builtins)
+ Builtin::Context &builtins, TranslationUnitKind TUKind)
: ConstantArrayTypes(this_()), FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()),
LangOpts.XRayAttrListFiles, SM)),
ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
- BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM),
- CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
+ BuiltinInfo(builtins), TUKind(TUKind), DeclarationNames(*this),
+ Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
CompCategories(this_()), LastSDM(nullptr, 0) {
- TUDecl = TranslationUnitDecl::Create(*this);
- TraversalScope = {TUDecl};
+ addTranslationUnitDecl();
}
ASTContext::~ASTContext() {
BuiltinTemplateDecl *
ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
const IdentifierInfo *II) const {
- auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK);
+ auto *BuiltinTemplate =
+ BuiltinTemplateDecl::Create(*this, getTranslationUnitDecl(), II, BTK);
BuiltinTemplate->setImplicit();
- TUDecl->addDecl(BuiltinTemplate);
+ getTranslationUnitDecl()->addDecl(BuiltinTemplate);
return BuiltinTemplate;
}
// MSVC predeclares struct _GUID, and we need it to create MSGuidDecls.
if (LangOpts.MicrosoftExt || LangOpts.Borland) {
MSGuidTagDecl = buildImplicitRecord("_GUID");
- TUDecl->addDecl(MSGuidTagDecl);
+ getTranslationUnitDecl()->addDecl(MSGuidTagDecl);
}
}
QualType ASTContext::getObjCSuperType() const {
if (ObjCSuperType.isNull()) {
RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super");
- TUDecl->addDecl(ObjCSuperTypeDecl);
+ getTranslationUnitDecl()->addDecl(ObjCSuperTypeDecl);
ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl);
}
return ObjCSuperType;
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
- DeclContext(TranslationUnit), Ctx(ctx) {}
+ DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
DeclContext *DeclContext::getPrimaryContext() {
switch (getDeclKind()) {
- case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Export:
// There is only one DeclContext for these entities.
return this;
+ case Decl::TranslationUnit:
+ return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
case Decl::Namespace:
// The original namespace is our primary context.
return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
}
}
-void
-DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
- Contexts.clear();
+template <typename T>
+void collectAllContextsImpl(T *Self, SmallVectorImpl<DeclContext *> &Contexts) {
+ for (T *D = Self->getMostRecentDecl(); D; D = D->getPreviousDecl())
+ Contexts.push_back(D);
- if (getDeclKind() != Decl::Namespace) {
- Contexts.push_back(this);
- return;
- }
+ std::reverse(Contexts.begin(), Contexts.end());
+}
- auto *Self = static_cast<NamespaceDecl *>(this);
- for (NamespaceDecl *N = Self->getMostRecentDecl(); N;
- N = N->getPreviousDecl())
- Contexts.push_back(N);
+void DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts) {
+ Contexts.clear();
- std::reverse(Contexts.begin(), Contexts.end());
+ Decl::Kind Kind = getDeclKind();
+
+ if (Kind == Decl::TranslationUnit)
+ collectAllContextsImpl(static_cast<TranslationUnitDecl *>(this), Contexts);
+ else if (Kind == Decl::Namespace)
+ collectAllContextsImpl(static_cast<NamespaceDecl *>(this), Contexts);
+ else
+ Contexts.push_back(this);
}
std::pair<Decl *, Decl *>
if (ToLoad >= LoadASTOnly)
AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ PP.getBuiltinInfo(),
+ AST->getTranslationUnitKind());
DisableValidationForModuleKind disableValid =
DisableValidationForModuleKind::None;
Preprocessor &PP = getPreprocessor();
auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ PP.getBuiltinInfo(), PP.TUKind);
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
setASTContext(Context);
}
#include "IncrementalParser.h"
+#include "clang/AST/DeclContextInternals.h"
#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/CodeGen/ModuleBuilder.h"
return Act;
}()) {}
FrontendAction *getWrapped() const { return WrappedAction.get(); }
+ TranslationUnitKind getTranslationUnitKind() override {
+ return TU_Incremental;
+ }
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
assert(CI.hasPreprocessor() && "No PP!");
IncrementalParser::~IncrementalParser() { Act->FinalizeAction(); }
-llvm::Expected<Transaction &> IncrementalParser::ParseOrWrapTopLevelDecl() {
- DiagnosticsEngine &Diags = getCI()->getDiagnostics();
-
- if (Diags.hasErrorOccurred())
- llvm::report_fatal_error("Previous input had errors, "
- "recovery not yet supported",
- /*GenCrashDiag=*/false);
-
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::ParseOrWrapTopLevelDecl() {
// Recover resources if we crash before exiting this method.
Sema &S = CI->getSema();
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true);
Sema::LocalEagerInstantiationScope LocalInstantiations(S);
+ PTUs.emplace_back(PartialTranslationUnit());
+ PartialTranslationUnit &LastPTU = PTUs.back();
+ // Add a new PTU.
+ ASTContext &C = S.getASTContext();
+ C.addTranslationUnitDecl();
+ LastPTU.TUPart = C.getTranslationUnitDecl();
+
// Skip previous eof due to last incremental input.
- if (P->getCurToken().is(tok::eof))
+ if (P->getCurToken().is(tok::eof)) {
P->ConsumeToken();
-
- Transactions.emplace_back(Transaction());
- Transaction &LastTransaction = Transactions.back();
+ // FIXME: Clang does not call ExitScope on finalizing the regular TU, we
+ // might want to do that around HandleEndOfTranslationUnit.
+ P->ExitScope();
+ S.CurContext = nullptr;
+ // Start a new PTU.
+ P->EnterScope(Scope::DeclScope);
+ S.ActOnTranslationUnitScope(P->getCurScope());
+ }
Parser::DeclGroupPtrTy ADecl;
for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl); !AtEOF;
return llvm::make_error<llvm::StringError>("Parsing failed. "
"The consumer rejected a decl",
std::error_code());
- LastTransaction.Decls.push_back(ADecl.get());
+ }
+
+ DiagnosticsEngine &Diags = getCI()->getDiagnostics();
+ if (Diags.hasErrorOccurred()) {
+ TranslationUnitDecl *MostRecentTU = C.getTranslationUnitDecl();
+ TranslationUnitDecl *PreviousTU = MostRecentTU->getPreviousDecl();
+ assert(PreviousTU && "Must have a TU from the ASTContext initialization!");
+ TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
+ assert(FirstTU);
+ FirstTU->RedeclLink.setLatest(PreviousTU);
+ C.TUDecl = PreviousTU;
+ S.TUScope->setEntity(PreviousTU);
+
+ // Clean up the lookup table
+ if (StoredDeclsMap *Map = PreviousTU->getLookupPtr()) {
+ for (auto I = Map->begin(); I != Map->end(); ++I) {
+ StoredDeclsList &List = I->second;
+ DeclContextLookupResult R = List.getLookupResult();
+ for (NamedDecl *D : R)
+ if (D->getTranslationUnitDecl() == MostRecentTU)
+ List.remove(D);
+ if (List.isNull())
+ Map->erase(I);
+ }
+ }
+
+ // FIXME: Do not reset the pragma handlers.
+ Diags.Reset();
+ return llvm::make_error<llvm::StringError>("Parsing failed.",
+ std::error_code());
}
// Process any TopLevelDecls generated by #pragma weak.
for (Decl *D : S.WeakTopLevelDecls()) {
DeclGroupRef DGR(D);
- LastTransaction.Decls.push_back(DGR);
Consumer->HandleTopLevelDecl(DGR);
}
LocalInstantiations.perform();
GlobalInstantiations.perform();
- Consumer->HandleTranslationUnit(S.getASTContext());
-
- if (Diags.hasErrorOccurred())
- return llvm::make_error<llvm::StringError>("Parsing failed.",
- std::error_code());
+ Consumer->HandleTranslationUnit(C);
- return LastTransaction;
+ return LastPTU;
}
static CodeGenerator *getCodeGen(FrontendAction *Act) {
return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
}
-llvm::Expected<Transaction &> IncrementalParser::Parse(llvm::StringRef input) {
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::Parse(llvm::StringRef input) {
Preprocessor &PP = CI->getPreprocessor();
assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
"Cannot enter source file.",
std::error_code());
- auto ErrOrTransaction = ParseOrWrapTopLevelDecl();
- if (auto Err = ErrOrTransaction.takeError())
- return std::move(Err);
+ auto PTU = ParseOrWrapTopLevelDecl();
+ if (!PTU)
+ return PTU.takeError();
if (PP.getLangOpts().DelayedTemplateParsing) {
// Microsoft-specific:
if (CodeGenerator *CG = getCodeGen(Act.get())) {
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
- CG->StartModule("incr_module_" + std::to_string(Transactions.size()),
+ CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
M->getContext());
- ErrOrTransaction->TheModule = std::move(M);
+ PTU->TheModule = std::move(M);
}
- return ErrOrTransaction;
+ return PTU;
}
} // end namespace clang
#ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
#define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
-#include "clang/Interpreter/Transaction.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
/// List containing every information about every incrementally parsed piece
/// of code.
- std::list<Transaction> Transactions;
+ std::list<PartialTranslationUnit> PTUs;
public:
IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
const CompilerInstance *getCI() const { return CI.get(); }
/// Parses incremental input by creating an in-memory file.
- ///\returns a \c Transaction which holds information about the \c Decls and
- /// \c llvm::Module corresponding to the input.
- llvm::Expected<Transaction &> Parse(llvm::StringRef Input);
+ ///\returns a \c PartialTranslationUnit which holds information about the
+ /// \c TranslationUnitDecl and \c llvm::Module corresponding to the input.
+ llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Input);
private:
- llvm::Expected<Transaction &> ParseOrWrapTopLevelDecl();
+ llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
};
} // end namespace clang
return IncrParser->getCI();
}
-llvm::Expected<Transaction &> Interpreter::Parse(llvm::StringRef Code) {
+llvm::Expected<PartialTranslationUnit &>
+Interpreter::Parse(llvm::StringRef Code) {
return IncrParser->Parse(Code);
}
-llvm::Error Interpreter::Execute(Transaction &T) {
+llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
assert(T.TheModule);
if (!IncrExecutor) {
const llvm::Triple &Triple =
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
+ assert(pp.TUKind == TUKind);
TUScope = nullptr;
isConstantEvaluatedOverride = false;
return;
}
+ if (!D->getDeclContext()) {
+ assert(isa<TranslationUnitDecl>(D) && "Not a TU?");
+ return;
+ }
+
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
// If this is a named declaration, complete it by looking it up
std::unique_ptr<ASTContext>
BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) {
+ auto &PP = CI.getPreprocessor();
auto AST = std::make_unique<ASTContext>(
CI.getLangOpts(), CI.getSourceManager(),
- CI.getPreprocessor().getIdentifierTable(), ST, BC);
+ PP.getIdentifierTable(), ST, BC, PP.TUKind);
AST->InitBuiltinTypes(CI.getTarget());
return AST;
}
: FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr), Idents(LangOpts, nullptr),
- Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins) {}
+ Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins, TU_Complete) {}
FileSystemOptions FileMgrOpts;
FileManager FileMgr;
auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv));
auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
- std::array<clang::Transaction *, 2> Transactions;
+ std::array<clang::PartialTranslationUnit *, 2> PTUs;
- Transactions[0] = &llvm::cantFail(Interp->Parse(TestProgram1));
- ASSERT_TRUE(Transactions[0]->TheModule);
- ASSERT_TRUE(Transactions[0]->TheModule->getFunction("funcForProg1"));
+ PTUs[0] = &llvm::cantFail(Interp->Parse(TestProgram1));
+ ASSERT_TRUE(PTUs[0]->TheModule);
+ ASSERT_TRUE(PTUs[0]->TheModule->getFunction("funcForProg1"));
- Transactions[1] = &llvm::cantFail(Interp->Parse(TestProgram2));
- ASSERT_TRUE(Transactions[1]->TheModule);
- ASSERT_TRUE(Transactions[1]->TheModule->getFunction("funcForProg2"));
+ PTUs[1] = &llvm::cantFail(Interp->Parse(TestProgram2));
+ ASSERT_TRUE(PTUs[1]->TheModule);
+ ASSERT_TRUE(PTUs[1]->TheModule->getFunction("funcForProg2"));
// First code should not end up in second module:
- ASSERT_FALSE(Transactions[1]->TheModule->getFunction("funcForProg1"));
+ ASSERT_FALSE(PTUs[1]->TheModule->getFunction("funcForProg1"));
// Make sure global inits exist and are unique:
- const Function *GlobalInit1 = getGlobalInit(Transactions[0]->TheModule.get());
+ const Function *GlobalInit1 = getGlobalInit(PTUs[0]->TheModule.get());
ASSERT_TRUE(GlobalInit1);
- const Function *GlobalInit2 = getGlobalInit(Transactions[1]->TheModule.get());
+ const Function *GlobalInit2 = getGlobalInit(PTUs[1]->TheModule.get());
ASSERT_TRUE(GlobalInit2);
ASSERT_FALSE(GlobalInit1->getName() == GlobalInit2->getName());
return cantFail(clang::Interpreter::create(std::move(CI)));
}
+static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
+ return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
+}
+
TEST(InterpreterTest, Sanity) {
std::unique_ptr<Interpreter> Interp = createInterpreter();
- Transaction &R1(cantFail(Interp->Parse("void g(); void g() {}")));
- EXPECT_EQ(2U, R1.Decls.size());
- Transaction &R2(cantFail(Interp->Parse("int i;")));
- EXPECT_EQ(1U, R2.Decls.size());
+ using PTU = PartialTranslationUnit;
+
+ PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
+ EXPECT_EQ(2U, DeclsSize(R1.TUPart));
+
+ PTU &R2(cantFail(Interp->Parse("int i;")));
+ EXPECT_EQ(1U, DeclsSize(R2.TUPart));
}
-static std::string DeclToString(DeclGroupRef DGR) {
- return llvm::cast<NamedDecl>(DGR.getSingleDecl())->getQualifiedNameAsString();
+static std::string DeclToString(Decl *D) {
+ return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString();
}
TEST(InterpreterTest, IncrementalInputTopLevelDecls) {
std::unique_ptr<Interpreter> Interp = createInterpreter();
- auto R1OrErr = Interp->Parse("int var1 = 42; int f() { return var1; }");
+ auto R1 = Interp->Parse("int var1 = 42; int f() { return var1; }");
// gtest doesn't expand into explicit bool conversions.
- EXPECT_TRUE(!!R1OrErr);
- auto R1 = R1OrErr->Decls;
- EXPECT_EQ(2U, R1.size());
- EXPECT_EQ("var1", DeclToString(R1[0]));
- EXPECT_EQ("f", DeclToString(R1[1]));
-
- auto R2OrErr = Interp->Parse("int var2 = f();");
- EXPECT_TRUE(!!R2OrErr);
- auto R2 = R2OrErr->Decls;
- EXPECT_EQ(1U, R2.size());
- EXPECT_EQ("var2", DeclToString(R2[0]));
+ EXPECT_TRUE(!!R1);
+ auto R1DeclRange = R1->TUPart->decls();
+ EXPECT_EQ(2U, DeclsSize(R1->TUPart));
+ EXPECT_EQ("var1", DeclToString(*R1DeclRange.begin()));
+ EXPECT_EQ("f", DeclToString(*(++R1DeclRange.begin())));
+
+ auto R2 = Interp->Parse("int var2 = f();");
+ EXPECT_TRUE(!!R2);
+ auto R2DeclRange = R2->TUPart->decls();
+ EXPECT_EQ(1U, DeclsSize(R2->TUPart));
+ EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin()));
}
TEST(InterpreterTest, Errors) {
HasSubstr("error: unknown type name 'intentional_error'"));
EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
-#ifdef GTEST_HAS_DEATH_TEST
- EXPECT_DEATH((void)Interp->Parse("int var1 = 42;"), "");
-#endif
+ auto RecoverErr = Interp->Parse("int var1 = 42;");
+ EXPECT_TRUE(!!RecoverErr);
}
// Here we test whether the user can mix declarations and statements. The
DiagnosticsOS, new DiagnosticOptions());
auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get());
- auto R1OrErr = Interp->Parse(
+ auto R1 = Interp->Parse(
"int var1 = 42; extern \"C\" int printf(const char*, ...);");
// gtest doesn't expand into explicit bool conversions.
- EXPECT_TRUE(!!R1OrErr);
+ EXPECT_TRUE(!!R1);
- auto R1 = R1OrErr->Decls;
- EXPECT_EQ(2U, R1.size());
+ auto *PTU1 = R1->TUPart;
+ EXPECT_EQ(2U, DeclsSize(PTU1));
// FIXME: Add support for wrapping and running statements.
- auto R2OrErr = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);");
- EXPECT_FALSE(!!R2OrErr);
+ auto R2 = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);");
+ EXPECT_FALSE(!!R2);
using ::testing::HasSubstr;
EXPECT_THAT(DiagnosticsOS.str(),
HasSubstr("error: unknown type name 'var1'"));
- auto Err = R2OrErr.takeError();
+ auto Err = R2.takeError();
EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
}
// according to LangOptions, so we init Parser to register opencl
// pragma handlers
ASTContext Context(OpenCLLangOpts, SourceMgr, PP.getIdentifierTable(),
- PP.getSelectorTable(), PP.getBuiltinInfo());
+ PP.getSelectorTable(), PP.getBuiltinInfo(), PP.TUKind);
Context.InitBuiltinTypes(*Target);
ASTConsumer Consumer;
void TypeSystemClang::SetExternalSource(
llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
ASTContext &ast = getASTContext();
- ast.setExternalSource(ast_source_up);
ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
+ ast.setExternalSource(ast_source_up);
}
ASTContext &TypeSystemClang::getASTContext() {
*m_diagnostics_engine_up, *m_file_manager_up);
m_ast_up = std::make_unique<ASTContext>(
*m_language_options_up, *m_source_manager_up, *m_identifier_table_up,
- *m_selector_table_up, *m_builtins_up);
+ *m_selector_table_up, *m_builtins_up, TU_Complete);
m_diagnostic_consumer_up = std::make_unique<NullDiagnosticConsumer>();
m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);