Segfault calling clang::parseAST on file with syntax error.

Hi everyone,

I’m working on a program to compile C++ code into llvm::Modules at the moment and am having trouble handling files with errors. I’m following along with the incremental processing unit test. The method in there works fine, unless the file its asked to parse contains an error in which case it segfaults. The problem seems to extend to clang::parseAST as well and I can reproduce it pretty easily. I attached a program to do that at the end of the email.

According to gdb, the segfault is happening in clang::DiagnosticRenderer::emitDiagnostic, but the stack trace other than that looks pretty good. The clang::Sema calls clang::Sema::DiagnoseUnknownTypeName which seems like the right idea.

Does anyone have any ideas why this might be happening or how to fix this? I’m also open to other ideas on how best to approach compiling C++ code into llvm::Modules from inside C++ land. Ultimately, I’d like to be able to JIT the resulting code with LLVM’s JIT.

Thanks,
Zeke

Program to reproduce

#include “clang/AST/ASTConsumer.h”
#include “clang/AST/ASTContext.h”
#include “clang/AST/RecursiveASTVisitor.h”
#include “clang/Basic/TargetInfo.h”
#include “clang/CodeGen/ModuleBuilder.h”
#include “clang/Frontend/CompilerInstance.h”
#include “clang/Lex/Preprocessor.h”
#include “clang/Parse/ParseAST.h”
#include “clang/Sema/Sema.h”
#include “llvm/ADT/Triple.h”
#include “llvm/IR/LLVMContext.h”
#include “llvm/Support/Host.h”
#include “llvm/Support/MemoryBuffer.h”

using namespace llvm;
using namespace clang;

const char TestProgram =
"class EmitCXXGlobalInitFunc "
"{ "
"public: "
" err EmitCXXGlobalInitFunc() {} " // I’ve added an error here.
"}; "
"EmitCXXGlobalInitFunc test; ";

int main()
{
LLVMContext Context;
CompilerInstance compiler;

compiler.createDiagnostics();
compiler.getLangOpts().CPlusPlus = 1;
compiler.getLangOpts().CPlusPlus11 = 1;

compiler.getTargetOpts().Triple = llvm::Triple::normalize(
llvm::sys::getProcessTriple());
compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
compiler.getDiagnostics(),
std::make_sharedclang::TargetOptions(
compiler.getTargetOpts())));

compiler.createFileManager();
compiler.createSourceManager(compiler.getFileManager());
compiler.createPreprocessor(clang::TU_Prefix);

compiler.createASTContext();

compiler.setASTConsumer(std::unique_ptr(
CreateLLVMCodeGen(
compiler.getDiagnostics(),
“EmitCXXGlobalInitFuncTest”,
compiler.getHeaderSearchOpts(),
compiler.getPreprocessorOpts(),
compiler.getCodeGenOpts(),
Context)));

compiler.createSema(clang::TU_Prefix, nullptr);

clang::SourceManager &sm = compiler.getSourceManager();
sm.setMainFileID(sm.createFileID(
llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));

clang::ParseAST(compiler.getSema(), false, false); // segfault here.
}

Stack Trace:

#0 0x0000000000df3c2f in clang::DiagnosticRenderer::emitDiagnostic(clang::FullSourceLoc, clang::DiagnosticsEngine::Level, llvm::StringRef, llvm::ArrayRefclang::CharSourceRange, llvm::ArrayRefclang::FixItHint, llvm::PointerUnion<clang::Diagnostic const*, clang::StoredDiagnostic const*>) ()
#1 0x0000000000dbe8d3 in clang::TextDiagnosticPrinter::HandleDiagnostic(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) ()
#2 0x0000000001ab8066 in clang::DiagnosticIDs::ProcessDiag(clang::DiagnosticsEngine&) const ()
#3 0x0000000001ab28a3 in clang::DiagnosticsEngine::EmitCurrentDiagnostic(bool) ()
#4 0x000000000117fa7a in clang::Sema::EmitCurrentDiagnostic(unsigned int) ()
#5 0x000000000123a528 in clang::Sema::DiagnoseUnknownTypeName(clang::IdentifierInfo*&, clang::SourceLocation, clang::Scope*, clang::CXXScopeSpec*, clang::OpaquePtrclang::QualType&, bool) ()
#6 0x0000000000f32aad in clang::Parser::ParseImplicitInt(clang::DeclSpec&, clang::CXXScopeSpec*, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::ParsedAttributesWithRange&) ()
#7 0x0000000000f2de92 in clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) ()
#8 0x0000000000f4bb6c in clang::Parser::ParseCXXClassMemberDeclaration(clang::AccessSpecifier, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo const&, clang::ParsingDeclRAIIObject*) ()
#9 0x0000000000f4e3a5 in clang::Parser::ParseCXXClassMemberDeclarationWithPragmas(clang::AccessSpecifier&, clang::Parser::ParsedAttributesWithRange&, clang::TypeSpecifierType, clang::Decl*) ()
#10 0x0000000000f49358 in clang::Parser::ParseCXXMemberSpecification(clang::SourceLocation, clang::SourceLocation, clang::Parser::ParsedAttributesWithRange&, unsigned int, clang::Decl*) ()
#11 0x0000000000f46e51 in clang::Parser::ParseClassSpecifier(clang::tok::TokenKind, clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, bool, clang::Parser::DeclSpecContext, clang::Parser::ParsedAttributesWithRange&) ()
#12 0x0000000000f2c05e in clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) ()
#13 0x0000000000f1827a in clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) ()
#14 0x0000000000f17f4c in clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) ()
#15 0x0000000000f17016 in clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) ()
#16 0x0000000000f15482 in clang::Parser::ParseTopLevelDecl(clang::OpaquePtrclang::DeclGroupRef&, bool) ()
#17 0x0000000000f14ff6 in clang::Parser::ParseFirstTopLevelDecl(clang::OpaquePtrclang::DeclGroupRef&) ()
#18 0x0000000000f10ac7 in clang::ParseAST(clang::Sema&, bool, bool) ()
#19 0x00000000006b1dd6 in main () at parseASTtest.cpp:68