-
Notifications
You must be signed in to change notification settings - Fork 14
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
Report inlining location when using __attribute__((__warning__(msg))) #1571
Comments
I think this is what |
In what way? |
Hmm...I guess not. A similar problem exists with inline asm: // $(CC) -O2
void __write_overflow(void) __attribute__((warning("eek")));
static inline void indirection(int x) {
if (__builtin_constant_p(x) && x > 10)
__write_overflow();
asm("# %0"::"i"(x));
}
void foo (int y) {
indirection(42);
indirection(y);
} in this case, the call to indirection with an integer constant expression is valid (and only due to inlining via optimizations being enabled), but the call without is not. GCC doesn't give precise info about which statement is problematic, but seems to have the infrastructure to do so. If we can implement similar behavior for the warnings attribute, then we likely can improve the case for asm, too. |
Until this is solved correctly in Clang, Nick has suggested a work-around can be used to help identify the inlining location for tracking down specific warnings with |
Reduced test case showing ambiguity between possible call sites: __attribute__((__warning__("foo")))
void foo(void);
static inline void bar(int x) {
if (x == 10)
foo();
}
void baz() {
bar(10);
}
void quux() {
bar(9);
} Clang:
GCC:
|
Even without inlining info, I think we can at least print/encode the "In function 'bar'" part. (Though the inlined from part is perhaps the more necessary part) |
I think we could add an IR Fn Attr to track "calls a dontwarn function" which is propagated during inline to the caller, at which point we record in the metadata the inlining chain. Though if we DCE the call, then we would have to remove the caller's fn attr. |
|
InlineFunction.cpp tracks struct ClonedCodeInfo.ContainsCalls. If that's set, we can scan the calls for calls to "dontcall-warn" attributed callees. |
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 6aaaa33cebde..ad6cc5b6232d 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2463,6 +2463,13 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
// inlining, commonly when the callee is an intrinsic.
if (MarkNoUnwind && !CI->doesNotThrow())
CI->setDoesNotThrow();
+
+ if (CI->getCalledFunction()->hasFnAttribute("dontcall-error") ||
+ CI->getCalledFunction()->hasFnAttribute("dontcall-warn")) {
+ MDString *VAM = MDString::get(CI->getContext(), CalledFunc->getName());
+ MDTuple *MDT = MDNode::get(CI->getContext(), {VAM});
+ CI->setMetadata("inlined-from", MDT);
+ }
}
}
} will record in the IR when we inline a call that is to one of the attributed functions: define dso_local void @baz() #0 {
entry:
call void @foo() #2, !srcloc !5, !inlined-from !6
ret void
}
...
!6 = !{!"bar"} though the metadata should be a list, since we might have multiple levels of inlining. We should probably first check if such metadata exists, and update it if so. |
ok, this produces a metadata of the mangled fn name, or appends a new value to the list if there's such existing metadata: diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 6aaaa33cebde..56a92f57ebee 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2463,6 +2463,18 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
// inlining, commonly when the callee is an intrinsic.
if (MarkNoUnwind && !CI->doesNotThrow())
CI->setDoesNotThrow();
+
+ if (CI->getCalledFunction()->hasFnAttribute("dontcall-error") ||
+ CI->getCalledFunction()->hasFnAttribute("dontcall-warn")) {
+ Metadata *MD = MDString::get(CI->getContext(), CalledFunc->getName());
+ if (MDNode *N = CI->getMetadata("inlined-from")) {
+ TempMDTuple Temp = cast<MDTuple>(N)->clone();
+ Temp->push_back(MD);
+ MD = MDNode::replaceWithUniqued(std::move(Temp));
+ }
+ MDTuple *MDT = MDNode::get(CI->getContext(), {MD});
+ CI->setMetadata("inlined-from", MDT);
+ }
}
}
}
|
D141451 doesn't seem to cross compilation units?
|
Due to inlining, descovering which specific call site to a function with the attribute "warning" or "error" is painful. In the IR record inlining decisions in metadata when inlining a callee that itself contains a call to a dontcall-error or dontcall-warn fn. Print this info so that it's clearer which call site is problematic. There's still some limitations with this approach; macro expansion is not recorded. Fixes: ClangBuiltLinux/linux#1571 Differential Revision: https://reviews.llvm.org/D141451
When
__warning__(msg)
reports from usage within an inline, there's no information about where the inline was used. For example:gcc says
inlined from 'main' at /app/example.c
Clang doesn't include that hint:
https://godbolt.org/z/W9PjxsE6z
Which makes FORTIFY_SOURCE warnings much harder to find. :)
The text was updated successfully, but these errors were encountered: