1*c57f0341SAlex Langford #include "clang/AST/DeclarationName.h"
2*c57f0341SAlex Langford #include "clang/Frontend/CompilerInstance.h"
3*c57f0341SAlex Langford #include "clang/Frontend/FrontendAction.h"
4*c57f0341SAlex Langford #include "clang/Parse/ParseAST.h"
5*c57f0341SAlex Langford #include "clang/Sema/Lookup.h"
6*c57f0341SAlex Langford #include "clang/Sema/Sema.h"
7*c57f0341SAlex Langford #include "clang/Tooling/Tooling.h"
8*c57f0341SAlex Langford #include "gtest/gtest.h"
9*c57f0341SAlex Langford
10*c57f0341SAlex Langford using namespace llvm;
11*c57f0341SAlex Langford using namespace clang;
12*c57f0341SAlex Langford using namespace clang::tooling;
13*c57f0341SAlex Langford
14*c57f0341SAlex Langford namespace {
15*c57f0341SAlex Langford
16*c57f0341SAlex Langford class LookupAction : public ASTFrontendAction {
17*c57f0341SAlex Langford std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef)18*c57f0341SAlex Langford CreateASTConsumer(CompilerInstance &CI, StringRef /*Unused*/) override {
19*c57f0341SAlex Langford return std::make_unique<clang::ASTConsumer>();
20*c57f0341SAlex Langford }
21*c57f0341SAlex Langford
ExecuteAction()22*c57f0341SAlex Langford void ExecuteAction() override {
23*c57f0341SAlex Langford CompilerInstance &CI = getCompilerInstance();
24*c57f0341SAlex Langford ASSERT_FALSE(CI.hasSema());
25*c57f0341SAlex Langford CI.createSema(getTranslationUnitKind(), nullptr);
26*c57f0341SAlex Langford ASSERT_TRUE(CI.hasSema());
27*c57f0341SAlex Langford Sema &S = CI.getSema();
28*c57f0341SAlex Langford ParseAST(S);
29*c57f0341SAlex Langford
30*c57f0341SAlex Langford ASTContext &Ctx = S.getASTContext();
31*c57f0341SAlex Langford auto Name = &Ctx.Idents.get("Foo");
32*c57f0341SAlex Langford LookupResult R_cpp(S, Name, SourceLocation(), Sema::LookupOrdinaryName);
33*c57f0341SAlex Langford S.LookupName(R_cpp, S.TUScope, /*AllowBuiltinCreation=*/false,
34*c57f0341SAlex Langford /*ForceNoCPlusPlus=*/false);
35*c57f0341SAlex Langford // By this point, parsing is done and S.TUScope is nullptr
36*c57f0341SAlex Langford // CppLookupName will perform an early return with no results if the Scope
37*c57f0341SAlex Langford // we pass in is nullptr. We expect to find nothing.
38*c57f0341SAlex Langford ASSERT_TRUE(R_cpp.empty());
39*c57f0341SAlex Langford
40*c57f0341SAlex Langford // On the other hand, the non-C++ path doesn't care if the Scope passed in
41*c57f0341SAlex Langford // is nullptr. We'll force the non-C++ path with a flag.
42*c57f0341SAlex Langford LookupResult R_nocpp(S, Name, SourceLocation(), Sema::LookupOrdinaryName);
43*c57f0341SAlex Langford S.LookupName(R_nocpp, S.TUScope, /*AllowBuiltinCreation=*/false,
44*c57f0341SAlex Langford /*ForceNoCPlusPlus=*/true);
45*c57f0341SAlex Langford ASSERT_TRUE(!R_nocpp.empty());
46*c57f0341SAlex Langford }
47*c57f0341SAlex Langford };
48*c57f0341SAlex Langford
TEST(SemaLookupTest,ForceNoCPlusPlusPath)49*c57f0341SAlex Langford TEST(SemaLookupTest, ForceNoCPlusPlusPath) {
50*c57f0341SAlex Langford const char *file_contents = R"objcxx(
51*c57f0341SAlex Langford @protocol Foo
52*c57f0341SAlex Langford @end
53*c57f0341SAlex Langford @interface Foo <Foo>
54*c57f0341SAlex Langford @end
55*c57f0341SAlex Langford )objcxx";
56*c57f0341SAlex Langford ASSERT_TRUE(runToolOnCodeWithArgs(std::make_unique<LookupAction>(),
57*c57f0341SAlex Langford file_contents, {"-x", "objective-c++"},
58*c57f0341SAlex Langford "test.mm"));
59*c57f0341SAlex Langford }
60*c57f0341SAlex Langford } // namespace
61