8000 Improved import of 'C implicit' functions. by balazske · Pull Request #689 · Ericsson/clang · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Mar 30, 2021. It is now read-only.

Improved import of 'C implicit' functions. #689

Merged
merged 2 commits into from
Jul 10, 2019

Conversation

balazske
Copy link
Collaborator
@balazske balazske commented Jul 9, 2019

No description provided.

@balazske
Copy link
Collaborator Author
balazske commented Jul 9, 2019

This fix still does not fix the error for #684 but maybe it is useful.

Copy link
@martong martong left a 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.

@@ -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();
Copy link

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.

Copy link

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() &&
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a function isCImplicit() ?

Copy link
Collaborator Author

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);
Copy link

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.

Copy link
Collaborator Author

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.)

Copy link

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);
Copy link

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.

@martong
Copy link
martong commented Jul 9, 2019

This fix still does not fix the error for #684 but maybe it is useful.

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.

@balazske
Copy link
Collaborator Author
balazske commented Jul 9, 2019

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).

8000

@balazske
Copy link
Collaborator Author
balazske commented Jul 9, 2019

Or we can generate the "UnsupportedConstruct" error for this case.

@martong
Copy link
martong commented Jul 9, 2019

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).

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.

@balazske
Copy link
Collaborator Author
balazske commented Jul 9, 2019

The test "ctu-main.c" contains this:

// The external function prototype is incomplete.
// warning:implicit functions are prohibited by c99
void testImplicit() {
  int res = identImplicit(6);   // external implicit functions are not inlined
  clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}

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?
The root cause of the SourceLocation problem in #684 is really that there is not a valid SourceLocation if the function is external implicit (but it is inlined because it is visited by the visitor). So that fix is correct if we want these functions to be inlined.

@martong
Copy link
martong commented Jul 9, 2019

The test "ctu-main.c" contains this:

// The external function prototype is incomplete.
// warning:implicit functions are prohibited by c99
void testImplicit() {
  int res = identImplicit(6);   // external implicit functions are not inlined
  clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}

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?

The root cause of the SourceLocation problem in #684 is really that there is not a valid SourceLocation if the function is external implicit (but it is inlined because it is visited by the visitor). So that fix is correct if we want these functions to be inlined.

So, if I understand it correctly then #684 will be solved by correctly importing the "external implicit" C functions without prototypes?
If that is the case then let's continue with this PR. Though I am confused now, because previously you wrote that this PR would not solve #684.

@balazske
Copy link
Collaborator Author
balazske commented Jul 9, 2019

The fix in this PR makes the links between multiple FunctionDecls (for same function) correct. Probably the analyzer still works correct by using the inlined definition for analysis but the "CallEvent" contains the CallExpr that contains the original FunctionDecl (regardless if there is a link to the definition of the inlined function). The same conditions appear if the fix in this PR is applied or not, the difference is that the getDefinition returns the correct inlined definition or not. In this way, this fix does not make something work that was wrong before (but makes the imported AST more correct, maybe later some problem appears that needs this fix).

@martong
Copy link
martong commented Jul 9, 2019

Ok.

Now I don't understand why we hadn't have any assertion before when we run the ctu-main.c test ? We do inline the "external implicit" identImplicit function there and without a SourceLocation, right?

@martong
Copy link
martong commented Jul 9, 2019

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:
We could have something similar what we have in ctu-main.c with identImplicit but in the other TU where identImplicit is defined we could make a division by zero. Then the bug path would go through the callExpr of idendImplicit ...

@balazske
Copy link
Collaborator Author

Finally in #690 there is a test to reproduce the problem in #684.
This fix is independent of those problems because these happens even with this fix applied. Still it is an improvement to ASTImporter so it can be useful.

@balazske balazske merged commit 446c84d into Ericsson:ctu-clang8 Jul 10, 2019
martong pushed a commit that referenced this pull request Sep 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0