-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathASTAction.cpp
More file actions
114 lines (100 loc) · 3.62 KB
/
Copy pathASTAction.cpp
File metadata and controls
114 lines (100 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// This is a derivative work. originally part of the LLVM Project.
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com)
// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
#include <lib/AST/ASTAction.hpp>
#include <lib/AST/ASTVisitorConsumer.hpp>
#include <lib/AST/MacroCollector.hpp>
#include <lib/AST/MrDocsFileSystem.hpp>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Parse/ParseAST.h>
#include <memory>
namespace mrdocs {
void
ASTAction::
ExecuteAction()
{
clang::CompilerInstance& CI = getCompilerInstance();
if (!CI.hasPreprocessor())
{
return;
}
// Register the macro collector before parsing begins.
// The preprocessor takes ownership; the records are
// pushed into `macroDefs_`, owned by this action.
CI.getPreprocessor().addPPCallbacks(
std::make_unique<MacroCollector>(
macroDefs_, CI.getPreprocessor()));
// Ensure comments in system headers are retained.
// We may want them if, e.g., a declaration was extracted
// as a dependency
auto &Lang = CI.getLangOpts();
Lang.RetainCommentsFromSystemHeaders = true;
bool const buildShims =
!config_.settings()->missingIncludePrefixes.empty() ||
!config_.settings()->missingIncludeShims.empty();
if (buildShims && missingSink_)
{
// Install missing symbol sink
missingSink_->setStartParsing();
auto &DE = CI.getDiagnostics();
std::unique_ptr<clang::DiagnosticConsumer> prev = DE.takeClient();
DE.setClient(
new CollectingDiagConsumer(*missingSink_, std::move(prev), DE),
/*ShouldOwnClient*/ true);
// Turn on AST recovery:
// Enable Clang’s recovery flags so it still builds
// decls/exprs with placeholder types when something is broken.
Lang.RecoveryAST = 1; // keep building AST nodes on errors
Lang.RecoveryASTType = 1; // synthesize placeholder types
// Mark stubbed prefixes as “system” for quieter diagnostics
for (auto &prefix : config_.settings()->missingIncludePrefixes)
{
MRDOCS_CHECK_OR_CONTINUE(!prefix.empty());
if (prefix.back() == '/')
{
CI.getHeaderSearchOpts().AddSystemHeaderPrefix(prefix, /*IsSystemHeader=*/true);
}
else
{
std::string p = prefix;
p += '/';
CI.getHeaderSearchOpts().AddSystemHeaderPrefix(p, /*IsSystemHeader=*/true);
}
}
}
// Skip function bodies:
// We don’t need bodies to enumerate symbols. This eliminates
// a ton of dependent code and template instantiations.
auto &FrontendOpts = CI.getFrontendOpts();
FrontendOpts.SkipFunctionBodies = true;
if (!CI.hasSema())
{
CI.createSema(getTranslationUnitKind(), nullptr);
}
ParseAST(
CI.getSema(),
false, // ShowStats
true); // SkipFunctionBodies
}
std::unique_ptr<clang::ASTConsumer>
ASTAction::
CreateASTConsumer(
clang::CompilerInstance& Compiler,
llvm::StringRef)
{
return std::make_unique<ASTVisitorConsumer>(
config_, ex_, Compiler, macroDefs_);
}
} // mrdocs