diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e2ae02ea9f76..d5b73686e84a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4252,8 +4252,8 @@ public: = NotForRedeclaration); bool LookupBuiltin(LookupResult &R); void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID); - bool LookupName(LookupResult &R, Scope *S, - bool AllowBuiltinCreation = false); + bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false, + bool ForceNoCPlusPlus = false); bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup = false); bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 65f5112afee3..ae3923854b52 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1931,13 +1931,14 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { /// used to diagnose ambiguities. /// /// @returns \c true if lookup succeeded and false otherwise. -bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { +bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation, + bool ForceNoCPlusPlus) { DeclarationName Name = R.getLookupName(); if (!Name) return false; LookupNameKind NameKind = R.getLookupKind(); - if (!getLangOpts().CPlusPlus) { + if (!getLangOpts().CPlusPlus || ForceNoCPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. if (NameKind == Sema::LookupRedeclarationWithLinkage) { diff --git a/clang/unittests/Sema/CMakeLists.txt b/clang/unittests/Sema/CMakeLists.txt index 194b7640b3c1..455c321d541b 100644 --- a/clang/unittests/Sema/CMakeLists.txt +++ b/clang/unittests/Sema/CMakeLists.txt @@ -7,6 +7,7 @@ add_clang_unittest(SemaTests ExternalSemaSourceTest.cpp CodeCompleteTest.cpp GslOwnerPointerInference.cpp + SemaLookupTest.cpp ) clang_target_link_libraries(SemaTests diff --git a/clang/unittests/Sema/SemaLookupTest.cpp b/clang/unittests/Sema/SemaLookupTest.cpp new file mode 100644 index 000000000000..d97b571f6a37 --- /dev/null +++ b/clang/unittests/Sema/SemaLookupTest.cpp @@ -0,0 +1,60 @@ +#include "clang/AST/DeclarationName.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Sema.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang; +using namespace clang::tooling; + +namespace { + +class LookupAction : public ASTFrontendAction { + std::unique_ptr + CreateASTConsumer(CompilerInstance &CI, StringRef /*Unused*/) override { + return std::make_unique(); + } + + void ExecuteAction() override { + CompilerInstance &CI = getCompilerInstance(); + ASSERT_FALSE(CI.hasSema()); + CI.createSema(getTranslationUnitKind(), nullptr); + ASSERT_TRUE(CI.hasSema()); + Sema &S = CI.getSema(); + ParseAST(S); + + ASTContext &Ctx = S.getASTContext(); + auto Name = &Ctx.Idents.get("Foo"); + LookupResult R_cpp(S, Name, SourceLocation(), Sema::LookupOrdinaryName); + S.LookupName(R_cpp, S.TUScope, /*AllowBuiltinCreation=*/false, + /*ForceNoCPlusPlus=*/false); + // By this point, parsing is done and S.TUScope is nullptr + // CppLookupName will perform an early return with no results if the Scope + // we pass in is nullptr. We expect to find nothing. + ASSERT_TRUE(R_cpp.empty()); + + // On the other hand, the non-C++ path doesn't care if the Scope passed in + // is nullptr. We'll force the non-C++ path with a flag. + LookupResult R_nocpp(S, Name, SourceLocation(), Sema::LookupOrdinaryName); + S.LookupName(R_nocpp, S.TUScope, /*AllowBuiltinCreation=*/false, + /*ForceNoCPlusPlus=*/true); + ASSERT_TRUE(!R_nocpp.empty()); + } +}; + +TEST(SemaLookupTest, ForceNoCPlusPlusPath) { + const char *file_contents = R"objcxx( +@protocol Foo +@end +@interface Foo +@end + )objcxx"; + ASSERT_TRUE(runToolOnCodeWithArgs(std::make_unique(), + file_contents, {"-x", "objective-c++"}, + "test.mm")); +} +} // namespace