-
Notifications
You must be signed in to change notification settings - Fork 10
Improved import of 'C implicit' functions. #689
Improved import of 'C implicit' functions. #689
Conversation
This fix still does not fix the error for #684 but maybe it is useful. |
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 naming implicit function
is really ambiguous. Clang AST contains several nodes (including functions) with the implicit tag. E.g. auto generated constructors, dtors are referred and signed as "implicit" in the AST. We even have an accessor function for that in the AST, see Decl::isImplicit
/// isImplicit - Indicates whether the declaration was implicitly
/// generated by the implementation. If false, this declaration
/// was written explicitly in the source code.
bool isImplicit() const { return Implicit; }
I think we should come up with a new naming for this both in the implementation and in the tests. We may call them something like "C function without prototype" (CFunctionWithoutPrototype) ?
Also, calling functions without prototype is not allowed in C99 and in C11, so this seems like a very borderline feature, I am not sure if we should spend so much time with this.
lib/AST/ASTImporter.cpp
Outdated
@@ -3048,9 +3047,12 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { | |||
} | |||
// Try to find a function in our own ("to") context with the same name, same | |||
// type, and in the same context as the function we're importing. | |||
else if (!LexicalDC->isFunctionOrMethod()) { | |||
else { | |||
bool IsCImplicit = LexicalDC->isFunctionOrMethod() && D->isImplicit(); |
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.
We could have a lambda for this, which we could reuse at line 3070: if (IsCImplicit(D) && IsCImplicit(FoundFunction)) { ... }
Note, probably we want to check the Lexical decl in the "from" context, and not in the "to" context, LexicalDC
is in the "to" context while D
is in the "from" ctx.
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.
Also, it would be nice to explain what do we mean under "C implicit" functions, perhaps with an example or with a reference to the paragraph in the C standard.
bool VisitCallExpr(CallExpr *E) { | ||
FunctionDecl *Callee = E->getDirectCallee(); | ||
// Our case: Declaration that is inside a function and implicit. | ||
if (Callee && Callee->getLexicalDeclContext()->isFunctionOrMethod() && |
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.
Add a function isCImplicit()
?
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 not needed to add it to FunctionDecl
because it is a rare case. And I am not sure if the conditions (for getLexicalDeclContext and isImplicit) are always correct and only true for this case.
auto *ToF2 = Import(FromF2, Lang_C); | ||
ASSERT_TRUE(ToImplicitF1); | ||
EXPECT_EQ(GetImplicitF(ToF1), ToImplicitF1); | ||
EXPECT_EQ(GetImplicitF(ToF2), ToImplicitF1); |
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.
Should there be a redecl chain here?
I'd expect that when we import f2 then we find the existing implicit_f
so the newly imported implict_f
should be linked to that as an additional decl in the same redecl chain.
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 would expect it too but the AST dump shows that there is no chain. In this code the same FunctionDecl
is used in f1
and f2
(source location returned by getLocation is valid and points to the first occurrence in f1
).
I do not know if it is problem is we create the redecl chain at import even if originally there is no chain. This would mean create a new FunctionDecl
instead of the MapImported
in ASTImporter. (Only to have less special cases in the code that may cause other new problems.)
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.
If the "from" AST does not have a redecl chain, then probably we should not have either, but then we should have an assert_xx for the no chain in the "from" ctx.
|
||
auto *ToImplicitF2 = Import(FromImplicitF2, Lang_C); | ||
ASSERT_TRUE(ToImplicitF2); | ||
EXPECT_EQ(ToImplicitF2, ToImplicitF1); |
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'd expect a redecl chain here as well.
Calling functions without prototype is not allowed in C99 and in C11 (AFAIK), so this seems like a very borderline feature, I am not sure if we should spend so much time with this. |
We can wait until the source of problems in #684 is found, probably this PR is not needed then (but still some old code can use the "C implicit function" feature) (but it could be a bug in the code too: the function is missing from the include file). |
Or we can generate the "UnsupportedConstruct" error for this case. |
Let's see if we can find the real root cause of #684. If there is no actual crash related to "C functions without prototype" then we might not need these changes. |
The test "ctu-main.c" contains this:
The comment says "external implicit functions are not inlined" but this is not true (without the fix too) because the function is inlined if it is found in the externapDefMap file. This test should be changed, or really the external implicit function should not be inlined? |
I think we should inline it, could you please change the comment in the test?
So, if I understand it correctly then #684 will be solved by correctly importing the "external implicit" C functions without prototypes? |
The fix in this PR makes the links between multiple |
Ok. Now I don't understand why we hadn't have any assertion before when we run the |
Perhaps that is because there is no bug reported, so the BugReporterVisitor is not invoked. Anyway this observation makes it cleaner to synthesize a test for #684: |
No description provided.