15 #include "clang/AST/RecursiveASTVisitor.h"
16 #include "clang/Basic/Diagnostic.h"
17 #include "clang/Frontend/CompilerInvocation.h"
18 #include "clang/Frontend/Utils.h"
26 ImportThunk =
testPath(
"import_thunk.h");
30 std::string ThunkContents =
"#import \"" + FullHeaderName +
"\"\n";
33 FS.Files[FullFilename] =
Code;
35 FS.Files[ImportThunk] = ThunkContents;
38 auto &Argv =
Inputs.CompileCommand.CommandLine;
43 Argv.push_back(
"-include");
48 Inputs.CompileCommand.CommandLine.push_back(
"-fno-ms-compatibility");
53 Argv.push_back(FullFilename);
54 Inputs.CompileCommand.Filename = FullFilename;
59 Inputs.Opts.BuildRecoveryAST =
true;
60 Inputs.Opts.PreserveRecoveryASTType =
true;
65 Inputs.Opts.SuggestMissingIncludes =
true;
74 assert(
CI &&
"Failed to build compilation invocation.");
85 assert(
CI &&
"Failed to build compilation invocation.");
91 if (!
AST.hasValue()) {
92 ADD_FAILURE() <<
"Failed to build code:\n" <<
Code;
93 llvm_unreachable(
"Failed to build TestTU!");
99 bool ErrorOk = [&,
this] {
100 llvm::StringLiteral Marker =
"error-ok";
101 if (llvm::StringRef(
Code).contains(Marker) ||
105 if (llvm::StringRef(KV.second).contains(Marker))
110 for (
const auto &D :
AST->getDiagnostics())
113 <<
"TestTU failed to build (suppress with /*error-ok*/): \n"
114 << D <<
"\n\nFor code:\n"
119 return std::move(*
AST);
125 AST.getPreprocessorPtr(),
126 AST.getCanonicalIncludes()));
136 auto Idx = std::make_unique<FileIndex>(
true);
138 AST.getASTContext(),
AST.getPreprocessorPtr(),
139 AST.getCanonicalIncludes());
141 return std::move(Idx);
145 const Symbol *Result =
nullptr;
146 for (
const Symbol &S : Slab) {
147 if (QName != (S.Scope + S.Name).str())
150 ADD_FAILURE() <<
"Multiple symbols named " << QName <<
":\n"
151 << *Result <<
"\n---\n"
153 assert(
false &&
"QName is not unique");
158 ADD_FAILURE() <<
"No symbol named " << QName <<
" in "
159 << ::testing::PrintToString(Slab);
160 assert(
false &&
"No symbol with QName");
166 llvm::SmallVector<llvm::StringRef, 4> Components;
167 QName.split(Components,
"::");
170 auto LookupDecl = [&
Ctx](
const DeclContext &Scope,
171 llvm::StringRef
Name) ->
const NamedDecl & {
172 auto LookupRes = Scope.lookup(DeclarationName(&
Ctx.Idents.
get(
Name)));
173 assert(!LookupRes.empty() &&
"Lookup failed");
174 assert(LookupRes.size() == 1 &&
"Lookup returned multiple results");
175 return *LookupRes.front();
178 const DeclContext *Scope =
Ctx.getTranslationUnitDecl();
179 for (
auto NameIt = Components.begin(), End = Components.end() - 1;
180 NameIt != End; ++NameIt) {
181 Scope = &cast<DeclContext>(LookupDecl(*Scope, *NameIt));
183 return LookupDecl(*Scope, Components.back());
187 std::function<
bool(
const NamedDecl &)> Filter) {
188 struct Visitor : RecursiveASTVisitor<Visitor> {
190 llvm::SmallVector<const NamedDecl *, 1> Decls;
191 bool VisitNamedDecl(
const NamedDecl *ND) {
198 Visitor.TraverseDecl(AST.
getASTContext().getTranslationUnitDecl());
199 if (Visitor.Decls.size() != 1) {
200 ADD_FAILURE() << Visitor.Decls.size() <<
" symbols matched.";
201 assert(Visitor.Decls.size() == 1);
203 return *Visitor.Decls.front();
208 if (
auto *ID = ND.getIdentifier())
209 if (ID->getName() ==
Name)