-
Notifications
You must be signed in to change notification settings - Fork 10
Conversation
lib/AST/ASTImporter.cpp
Outdated
auto *Recent = const_cast<VarDecl *>(MergeWithVar->getMostRecentDecl()); | ||
updateAttrAndFlags(D, MergeWithVar); | ||
ToVar->setPreviousDecl(Recent); | ||
} | ||
|
||
// Merge the initializer. |
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.
This is not a "merge" rather an import.
unittests/AST/ASTImporterTest.cpp
Outdated
ASSERT_TRUE(ToD0); | ||
ASSERT_TRUE(ToD1); | ||
EXPECT_NE(ToD0, ToD1); | ||
EXPECT_EQ(ToD1->getPreviousDecl() ,ToD0); |
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.
Better variable names can be used: FromDWithInit
, FromDWithDef
and similar.
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, good point.
@@ -1421,13 +1423,22 @@ bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To, | |||
if (To->getAnyInitializer()) | |||
return false; | |||
|
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.
Really this function does not ensure the definition, only the initializer? (If "definition" is not the same as initializer.)
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, the definition may be independent from the initializer.
Perhaps a better name would be just ImportInitializer
.
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.
Renamed to ImportInitializer
.
lib/AST/ASTImporter.cpp
Outdated
LexicalDC->addDeclInternal(ToVar); | ||
if (MergeWithVar) { | ||
auto *Recent = const_cast<VarDecl *>(MergeWithVar->getMostRecentDecl()); | ||
updateAttrAndFlags(D, MergeWithVar); |
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.
The updateAttrAndFlags
is used to update data (from D
) in the found Decl. I think this should be called at the MapImported
cases (line 3223 and 3229).
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.
This will not work that way. Just tried and moved updateAttrAndFlags
before the MapImported calls, and the unit test which test the used flag fails.
If we think about it this is logical, since we should update the used flag when we do create a new VarDecl, and that is happening once we reach to this line.
In those lines you mentioned (line 3223 and 3229) we do not create any new declaration, thus there is nothing to update.
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.
Probably include it in both places? At create the used flag should be copied anyway. If an imported Decl is mapped to an existing, the imported may have the used flag set but the existing not, in this case the update is needed. Probably this case does not occur any more in the unit test because way of importing has changed (but the unit test originally was made to test the case when there is an existing VarDecl
and an imported VarDecl
is mapped to that and the used flag should be updated).
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.
Okay, makes sense, I am going to check that and also the test.
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, I've written two new test cases which exercises those cases. And indeed it is needed to add updateAttrAndFlags
there.
Then I realized that we have to do this always after we found an existing decl or even if we created a new one.
This seems like a general rule, so I added the call of updateAttrAndFlags
into Import::(Decl*)
.
lib/AST/ASTImporter.cpp
Outdated
@@ -3178,8 +3199,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { | |||
|
|||
// Try to find a variable in our own ("to") context with the same name and | |||
// in the same context as the variable we're importing. | |||
VarDecl *MergeWithVar = nullptr; |
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.
This should be renamed to ExistingVar
or similar.
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.
Renamed to FoundByLookup
, since that is how we call it in VisitFunctionDecl
too.
Added a new commit, so you can easily track what changed, before merge I'll squash. |
lib/AST/ASTImporter.cpp
Outdated
VarDecl *FoundDef = FoundVar->getDefinition(); | ||
if (D->isThisDeclarationADefinition() && FoundDef) { | ||
return Importer.MapImported(D, FoundDef); | ||
} |
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.
Is there no problem with update of initializer? If the D
is definition and has initializer, and the found has no initializer, it is not updated. (But theoretically the variable can have only one definition, so the definition of D
should be the same as the found one, with initializer.)
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.
Hmm, good point, but I don't think that could be a problem exactly because what you have written in the parentheses.
I would not merge the initializer. Intstead, we could diagnose an ODR error here if we see that the two definitions have different initializers, I added a FIXME for that.
run tests |
1 similar comment
run tests |
@@ -3211,11 +3246,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { | |||
return nullptr; |
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.
I am not sure if this array type import is needed with the new code. The FoundVar
is updated (setType
) but later we create a new VarDecl
instead (and if a new VarDecl is created it should contain all new information, the existing should not be changed, no "merge" is done).
In line 3239 the getToContext
is used with D
that is in the FromContext
, is this correct?
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, I agree, this comes from the "From" context.
Also, I created a new issue to revisit this code: #485
unittests/AST/ASTImporterTest.cpp
Outdated
Decl *FromTU = getTuDecl( | ||
"int x = 1; int f() { return x; }", Lang_CXX, "input1.cc"); | ||
auto *FromD = | ||
FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); |
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.
This is good if we are sure that there is not any other hidden generated function in FromTU
. Better is to match always with name.
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.
Good catch, thank you.
Update: squashed the commits into one. |
Fixes #477