Author: martong Date: Fri May 18 02:08:47 2018 New Revision: 332699 URL: http://llvm.org/viewvc/llvm-project?rev=332699&view=rev Log: Do not try to remove invisible Decls from DeclContext
Modified: cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=332699&r1=332698&r2=332699&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Fri May 18 02:08:47 2018 @@ -1347,6 +1347,32 @@ bool DeclContext::containsDecl(Decl *D) (D->NextInContextAndBits.getPointer() || D == LastDecl)); } +/// shouldBeHidden - Determine whether a declaration which was declared +/// within its semantic context should be invisible to qualified name lookup. +static bool shouldBeHidden(NamedDecl *D) { + // Skip unnamed declarations. + if (!D->getDeclName()) + return true; + + // Skip entities that can't be found by name lookup into a particular + // context. + if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) || + D->isTemplateParameter()) + return true; + + // Skip template specializations. + // FIXME: This feels like a hack. Should DeclarationName support + // template-ids, or is there a better way to keep specializations + // from being visible? + if (isa<ClassTemplateSpecializationDecl>(D)) + return true; + if (auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isFunctionTemplateSpecialization()) + return true; + + return false; +} + void DeclContext::removeDecl(Decl *D) { assert(D->getLexicalDeclContext() == this && "decl being removed from non-lexical context"); @@ -1369,7 +1395,7 @@ void DeclContext::removeDecl(Decl *D) { } } } - + // Mark that D is no longer in the decl chain. D->NextInContextAndBits.setPointer(nullptr); @@ -1377,8 +1403,14 @@ void DeclContext::removeDecl(Decl *D) { if (isa<NamedDecl>(D)) { auto *ND = cast<NamedDecl>(D); + // Do not try to remove the declaration if that is invisible to qualified + // lookup. E.g. template specializations are skipped. + if (shouldBeHidden(ND)) + return; + // Remove only decls that have a name - if (!ND->getDeclName()) return; + if (!ND->getDeclName()) + return; auto *DC = D->getDeclContext(); do { @@ -1435,32 +1467,6 @@ void DeclContext::addDeclInternal(Decl * makeDeclVisibleInContextWithFlags(ND, true, true); } -/// shouldBeHidden - Determine whether a declaration which was declared -/// within its semantic context should be invisible to qualified name lookup. -static bool shouldBeHidden(NamedDecl *D) { - // Skip unnamed declarations. - if (!D->getDeclName()) - return true; - - // Skip entities that can't be found by name lookup into a particular - // context. - if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) || - D->isTemplateParameter()) - return true; - - // Skip template specializations. - // FIXME: This feels like a hack. Should DeclarationName support - // template-ids, or is there a better way to keep specializations - // from being visible? - if (isa<ClassTemplateSpecializationDecl>(D)) - return true; - if (auto *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isFunctionTemplateSpecialization()) - return true; - - return false; -} - /// buildLookup - Build the lookup data structure with all of the /// declarations in this DeclContext (and any other contexts linked /// to it or transparent contexts nested within it) and return it. Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=332699&r1=332698&r2=332699&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Fri May 18 02:08:47 2018 @@ -1797,5 +1797,38 @@ TEST(ImportExpr, UnresolvedMemberExpr) { compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))))); } +struct DeclContextTest : ASTImporterTestBase {}; + +TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { + Decl *TU = getTuDecl( + R"( + namespace NS { + + template <typename T> + struct S {}; + template struct S<int>; + + inline namespace INS { + template <typename T> + struct S {}; + template struct S<int>; + } + + } + )", Lang_CXX11, "input0.cc"); + auto *NS = FirstDeclMatcher<NamespaceDecl>().match( + TU, namespaceDecl()); + auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( + TU, classTemplateSpecializationDecl()); + ASSERT_TRUE(NS->containsDecl(Spec)); + + NS->removeDecl(Spec); + EXPECT_FALSE(NS->containsDecl(Spec)); +} + +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, DeclContextTest, + ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),); + } // end namespace ast_matchers } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits