-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][ASTImporter] Not using primary context in lookup table #118466
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6063,7 +6063,7 @@ TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) { | |
EXPECT_EQ(*Res.begin(), A); | ||
} | ||
|
||
TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) { | ||
TEST_P(ASTImporterLookupTableTest, LookupSearchesInActualNamespaceOnly) { | ||
TranslationUnitDecl *ToTU = getToTuDecl( | ||
R"( | ||
namespace N { | ||
|
@@ -6073,7 +6073,9 @@ TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) { | |
} | ||
)", | ||
Lang_CXX03); | ||
auto *N1 = | ||
auto *N1 = FirstDeclMatcher<NamespaceDecl>().match( | ||
ToTU, namespaceDecl(hasName("N"))); | ||
auto *N2 = | ||
LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N"))); | ||
auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A"))); | ||
DeclarationName Name = A->getDeclName(); | ||
|
@@ -6082,6 +6084,7 @@ TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) { | |
auto Res = LT.lookup(N1, Name); | ||
ASSERT_EQ(Res.size(), 1u); | ||
EXPECT_EQ(*Res.begin(), A); | ||
EXPECT_TRUE(LT.lookup(N2, Name).empty()); | ||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, | ||
|
@@ -10181,6 +10184,151 @@ TEST_P(ImportTemplateParmDeclDefaultValue, | |
FromD, FromDInherited); | ||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch1) { | ||
const char *ToCode = | ||
R"( | ||
namespace a { | ||
} | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
)"; | ||
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); | ||
const char *Code = | ||
R"( | ||
namespace a { | ||
struct X { char A; }; | ||
} | ||
)"; | ||
Decl *FromTU = getTuDecl(Code, Lang_CXX11); | ||
auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
FromTU, cxxRecordDecl(hasName("X"))); | ||
auto *ImportedX = Import(FromX, Lang_CXX11); | ||
EXPECT_FALSE(ImportedX); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this would've succeeded in the past? I guess because the primary context would've just return the empty namespace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test should pass in the previous code too. This is because all of the declarations are added to the primary context at the lookup table (before the changes), |
||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch2) { | ||
const char *ToCode = | ||
R"( | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
namespace a { | ||
} | ||
)"; | ||
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); | ||
const char *Code = | ||
R"( | ||
namespace a { | ||
struct X { char A; }; | ||
} | ||
)"; | ||
Decl *FromTU = getTuDecl(Code, Lang_CXX11); | ||
auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
FromTU, cxxRecordDecl(hasName("X"))); | ||
auto *ImportedX = Import(FromX, Lang_CXX11); | ||
EXPECT_FALSE(ImportedX); | ||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch1) { | ||
const char *ToCode = | ||
R"( | ||
namespace a { | ||
} | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
)"; | ||
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); | ||
const char *Code = | ||
R"( | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
)"; | ||
Decl *FromTU = getTuDecl(Code, Lang_CXX11); | ||
auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
FromTU, cxxRecordDecl(hasName("X"))); | ||
auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
ToTU, cxxRecordDecl(hasName("X"))); | ||
auto *ImportedX = Import(FromX, Lang_CXX11); | ||
EXPECT_EQ(ImportedX, ToX); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this have failed in the past? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think not, for the same reason as already explained. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The last test is the ones that fails before the changes. The template parameter objects have the record declaration (of the template) as DeclContext and in that case a definition of it is imported. This results in change of the primary context (even for first |
||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch2) { | ||
const char *ToCode = | ||
R"( | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
namespace a { | ||
} | ||
)"; | ||
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); | ||
const char *Code = | ||
R"( | ||
namespace a { | ||
struct X { int A; }; | ||
} | ||
)"; | ||
Decl *FromTU = getTuDecl(Code, Lang_CXX11); | ||
auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
FromTU, cxxRecordDecl(hasName("X"))); | ||
auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match( | ||
ToTU, cxxRecordDecl(hasName("X"))); | ||
auto *ImportedX = Import(FromX, Lang_CXX11); | ||
EXPECT_EQ(ImportedX, ToX); | ||
} | ||
|
||
TEST_P(ASTImporterLookupTableTest, PrimaryDCChangeAtImport) { | ||
const char *ToCode = | ||
R"( | ||
template <class T> | ||
struct X; | ||
)"; | ||
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); | ||
auto *ToX = FirstDeclMatcher<ClassTemplateDecl>().match( | ||
ToTU, classTemplateDecl(hasName("X"))); | ||
NamedDecl *ToParm = ToX->getTemplateParameters()->getParam(0); | ||
DeclContext *OldPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext(); | ||
ASSERT_EQ(ToParm->getDeclContext(), ToX->getTemplatedDecl()); | ||
ASSERT_EQ(SharedStatePtr->getLookupTable() | ||
->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName()) | ||
.size(), | ||
1u); | ||
ASSERT_TRUE(SharedStatePtr->getLookupTable()->contains( | ||
ToX->getTemplatedDecl(), ToParm)); | ||
|
||
const char *Code = | ||
R"( | ||
template <class T> | ||
struct X; | ||
template <class T> | ||
struct X {}; | ||
)"; | ||
Decl *FromTU = getTuDecl(Code, Lang_CXX11); | ||
auto *FromX = LastDeclMatcher<ClassTemplateDecl>().match( | ||
FromTU, classTemplateDecl(hasName("X"))); | ||
|
||
auto *ImportedX = Import(FromX, Lang_CXX11); | ||
|
||
EXPECT_TRUE(ImportedX); | ||
EXPECT_EQ(ImportedX->getTemplateParameters()->getParam(0)->getDeclContext(), | ||
ImportedX->getTemplatedDecl()); | ||
|
||
// ToX did not change at the import. | ||
// Verify that primary context has changed after import of class definition. | ||
DeclContext *NewPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext(); | ||
EXPECT_NE(OldPrimaryDC, NewPrimaryDC); | ||
// The lookup table should not be different than it was before. | ||
EXPECT_EQ(SharedStatePtr->getLookupTable() | ||
->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName()) | ||
.size(), | ||
1u); | ||
EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( | ||
ToX->getTemplatedDecl(), ToParm)); | ||
} | ||
|
||
TEST_P(ASTImporterOptionSpecificTestBase, | ||
ExistingUndeclaredImportDeclaredFriend) { | ||
Decl *ToTU = getToTuDecl( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So prior to your change this lookup would've found
A
? Because theLookupTable
would unconditionally use the primary context?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, previously always the primary context was used.
(It is possible to use the primary context in the lookup table only for namespaces, not for other decls. But this exception makes the lookup table more complicated.)