1//===-- Fuzzer.cpp - Fuzz the pseudoparser --------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang-pseudo/DirectiveTree.h"
10#include "clang-pseudo/Forest.h"
11#include "clang-pseudo/GLR.h"
12#include "clang-pseudo/Token.h"
13#include "clang-pseudo/cli/CLI.h"
14#include "clang-pseudo/grammar/Grammar.h"
15#include "clang-pseudo/grammar/LRTable.h"
16#include "clang/Basic/LangOptions.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/MemoryBuffer.h"
19#include "llvm/Support/raw_ostream.h"
20#include <algorithm>
21
22namespace clang {
23namespace pseudo {
24namespace {
25
26class Fuzzer {
27 clang::LangOptions LangOpts = clang::pseudo::genericLangOpts();
28 bool Print;
29
30public:
31 Fuzzer(bool Print) : Print(Print) {}
32
33 void operator()(llvm::StringRef Code) {
34 std::string CodeStr = Code.str(); // Must be null-terminated.
35 auto RawStream = lex(CodeStr, LangOpts);
36 auto DirectiveStructure = DirectiveTree::parse(RawStream);
37 clang::pseudo::chooseConditionalBranches(DirectiveStructure, Code: RawStream);
38 // FIXME: strip preprocessor directives
39 auto ParseableStream =
40 clang::pseudo::stripComments(cook(RawStream, LangOpts));
41
42 clang::pseudo::ForestArena Arena;
43 clang::pseudo::GSS GSS;
44 const Language &Lang = getLanguageFromFlags();
45 auto &Root =
46 glrParse(Params: clang::pseudo::ParseParams{.Code: ParseableStream, .Forest: Arena, .GSStack: GSS},
47 StartSymbol: *Lang.G.findNonterminal(Name: "translation-unit"), Lang);
48 if (Print)
49 llvm::outs() << Root.dumpRecursive(Lang.G);
50 }
51};
52
53Fuzzer *Fuzz = nullptr;
54
55} // namespace
56} // namespace pseudo
57} // namespace clang
58
59extern "C" {
60
61// Set up the fuzzer from command line flags:
62// -print - used for testing the fuzzer
63int LLVMFuzzerInitialize(int *Argc, char ***Argv) {
64 bool PrintForest = false;
65 auto ConsumeArg = [&](llvm::StringRef Arg) -> bool {
66 if (Arg == "-print") {
67 PrintForest = true;
68 return true;
69 }
70 return false;
71 };
72 *Argc = std::remove_if(first: *Argv + 1, last: *Argv + *Argc, pred: ConsumeArg) - *Argv;
73
74 clang::pseudo::Fuzz = new clang::pseudo::Fuzzer(PrintForest);
75 return 0;
76}
77
78int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
79 (*clang::pseudo::Fuzz)(llvm::StringRef(reinterpret_cast<char *>(Data), Size));
80 return 0;
81}
82}
83

source code of clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp