Clang AST находит только синтаксические ошибки - PullRequest
1 голос
/ 17 июня 2020

Я использую Clang для создания некоторых внутренних c анализаторов кода. Для одного из анализаторов нам нужно взять необработанную строку и проверить, нет ли в ней синтаксических ошибок. Мы не должны учитывать отсутствующие символы, заголовки, недопустимые вызовы функций и т. Д. c. как недопустимый синтаксис - поскольку единственное значение - проверить, является ли он действительным кодом C / C ++ или нет.

Сначала я думал, что могу сделать это с помощью ASTUnit:

  auto AST = tooling::buildASTFromCodeWithArgs(MyCode,
                                               Args,
                                               "input.cc",
                                               "clang-tool",
                                               std::make_shared<PCHContainerOperations>(),
                                               tooling::getClangStripDependencyFileAdjuster(),
                                               tooling::FileContentMappings(),
                                               &DiagConsumer);

  llvm::outs() << "hasUncompilableErrorOccurred " << AST->getDiagnostics().hasUncompilableErrorOccurred() << "\n";
  llvm::outs() << "hasUnrecoverableErrorOccurred " << AST->getDiagnostics().hasUnrecoverableErrorOccurred() << "\n";
  llvm::outs() << "hasErrorOccurred " << AST->getDiagnostics().hasErrorOccurred() << "\n";

Принимая два входа: Hello world и #include <undefined.h> - оба дают 1 в выходных данных выше - даже если #include <undefined.h> является правильным выражением C, но проблема с ним (в отличие от hello world, который не является допустимым C код) - это то, что undefined.h отсутствует. Точно так же использование: int* p = malloc(sizeof(int)); в качестве кода приведет к ошибке во всех этих вызовах, если stdlib.h не было включено.

Я стараюсь избегать таких ошибок, поэтому во всех случаях, кроме hello world, будет считаться действительным кодом.

Я пытался перебрать его, создав Raw Lexer, но он не дал мне достаточной информации.

  Lexer Lex(CharRange.getBegin(), PP->getLangOpts(), Text.data(),
                       Text.data(), Text.data() + Text.size());

  Token RawTok;
  do {
    Lex.LexFromRawLexer(RawTok);
    llvm::outs() << "\t- " << RawTok.getKind() << "\n";
  } while (RawTok.isNot(tok::eof));

Я бы хотел получить любые предложения!

...