aaron.ballman added inline comments.

================
Comment at: clang/include/clang/Basic/Attr.td:3819
+  let Args = [StringArgument<"UserDiagnostic">];
+  let Subjects = SubjectList<[Function], ErrorDiag>;
+  let Documentation = [ErrorAttrDocs];
----------------
nickdesaulniers wrote:
> aaron.ballman wrote:
> > nickdesaulniers wrote:
> > > aaron.ballman wrote:
> > > > ObjC methods as well?
> > > I guess I can add them, but I'm unfamiliar with the language. If there's 
> > > no GNU implementation of an ObjC compiler, do we need to worry about GNU 
> > > C extensions in ObjC?
> > There's nothing platform-specific about the semantics of these attributes, 
> > so GNU or not doesn't really matter. I'm fine holding off on ObjC methods 
> > until a user requests support for it, but given how these are generally 
> > useful attributes, I think it would make sense to support ObjC up front 
> > unless there's a burden from supporting it.
> Looking at the generated IR for ObjC method calls, I don't think we can 
> support them (easily).
> 
> It looks like method calls in ObjC are lowered to direct calls to 
> `objc_msg_lookup`+indirect CALLs, IIUC.  This BackendDiagnostic relies on 
> observing direct calls during instruction selection. (I suspect ObjC supports 
> runtime modification of classes?) So during instruction selection, we can't 
> know that we're making a method call to a particular method (easily; maybe 
> there's helpers for this though?).  We don't seem to remove the indirection 
> even with optimizations enabled (making me think that methods can be swapped 
> at runtime).
> 
> We could try to diagnose in the frontend, but this very very quickly falls 
> apart if there's any control flow involved.  ie. maybe we could diagnose:
> ```
> void foo(void) { dontcall(); }
> ```
> but this whole BackendDiagnostic relies on the backend to run optimizations; 
> the frontend couldn't diagnose:
> ```
> void foo(void) { if (myRuntimeAssertion) dontcall(); }
> ```
> which is the predominate use case for this fn attr.
> 
> That said, the patch as is works for functions (not ObjC methods) in 
> objective-c mode already; would you like a test for that?
> 
> Marking as Done, please reopen this thread if I'm mistaken in this analysis.
> That said, the patch as is works for functions (not ObjC methods) in 
> objective-c mode already; would you like a test for that?

No thanks, I think the existing C coverage handles that.

> Marking as Done, please reopen this thread if I'm mistaken in this analysis.

Thanks for checking this out, I think it's a good reason to say "let's deal 
with this later (if ever)".


================
Comment at: clang/lib/CodeGen/CodeGenAction.cpp:783
+  else
+    Diags.Report(DiagID) << CalleeName << D.getMsgStr();
+}
----------------
nickdesaulniers wrote:
> aaron.ballman wrote:
> > nickdesaulniers wrote:
> > > nickdesaulniers wrote:
> > > > aaron.ballman wrote:
> > > > > nickdesaulniers wrote:
> > > > > > aaron.ballman wrote:
> > > > > > > I think the usability in this situation is a concern -- only 
> > > > > > > having a function name but no source location information is 
> > > > > > > pretty tricky. Do you have a sense for how often we would hit 
> > > > > > > this case?
> > > > > > I don't think we ever encounter it when building the kernel 
> > > > > > sources. Perhaps I should make this an assertion on 
> > > > > > `LocCookie.isValid()` instead?
> > > > > > 
> > > > > > While clang should always attach a `srcloc` MetaData node, other 
> > > > > > frontend might not, so it's optional.  But this TU is strictly 
> > > > > > Clang.
> > > > > I thought backend optimization passes would drop source location 
> > > > > information with some regularity, so I'm a bit hesitant to go with an 
> > > > > assertion unless it turns out I'm wrong there. However, if the 
> > > > > backend shouldn't ever lose *this* source location information, then 
> > > > > I think it's good to make it an assertion.
> > > > Perhaps debug info, but this SourceLocation is squirreled away in a 
> > > > Metadata node attached to the call site.
> > > > 
> > > > Ah, but via further testing of @arsenm 's point ("what about indirect 
> > > > calls?"), this case is tricky:
> > > > ```
> > > > // clang -O2 foo.c
> > > > __attribute__((error("oh no foo")))
> > > > void foo(void);
> > > > 
> > > > void (*bar)(void);
> > > > 
> > > > void baz(void) {
> > > >   bar = foo;
> > > >   bar();
> > > > }
> > > > ```
> > > > since we did not emit the Metadata node on the call, but then later 
> > > > during optimizations we replaced the call to `bar` with a call to 
> > > > `foo`. At that point, the front end did not emit a Metadata node with 
> > > > source location information, so we can't reconstruct the call site 
> > > > properly for the diagnostic. Hmm...I'll need to think more about this 
> > > > case.
> > > One thing I was thinking of to support @arsenm's case:
> > > 
> > > We probably generally could support diagnosing indirect calls if `-g` was 
> > > used to emit `DILocation` MD nodes.  I'd need to change this up from a 
> > > custom `!srcloc` node with one `unsigned` that is a `SourceLocation` to 
> > > use the the `DILocation` tuple of `line`, `column`, and `scope` then 
> > > change the frontend's `BackendDiagnosticConsumer` to reinstantiate a 
> > > `SourceLocation` from those (if possible).
> > > 
> > > The only thing is: is it bad if we can only diagnose with `-g` for 
> > > indirect calls?
> > > 
> > > Otherwise I don't see how we can support diagnosing indirect calls. GCC 
> > > can.  We'd perhaps need to emit `!srcloc` or `DILocation` nodes for EVERY 
> > > indirect call from the frontend, and add logic to merge these or 
> > > something during optimizations when we turn indirect calls into direct 
> > > calls.  And I'm sure that would cause lots of churn in the LLVM source 
> > > tree / in the tests. I would create a parent revision to precommit that.  
> > > But I think that's maybe too overkill?
> > > 
> > > The current behavior is that we don't diagnose indirect calls.  I'm happy 
> > > to add documentation, or create child or parent revisions trying to 
> > > tackle that, but I think if we can't provide accurate debug info, it's 
> > > perhaps better not to diagnose at all.
> > > 
> > > I could change that so that we still emit the diagnostic, but don't show 
> > > _where_ the callsite was in the sources as part of the diagnostic.  But I 
> > > think it's perhaps better to simply not warn in that case when we can't 
> > > provide line info.
> > > 
> > > But this can go either way, so I appreciate others' guidance and thoughts 
> > > here.
> > > Perhaps debug info, but this SourceLocation is squirreled away in a 
> > > Metadata node attached to the call site.
> > 
> > I thought optimization passes frequently drop metadata nodes?
> > I thought optimization passes frequently drop metadata nodes?
> 
> Perhaps, but I've yet to see Metadata attached to a static `call` get 
> dropped.  This patch emits such Metadata attached to `call` IR Instructions 
> when the frontend sees a static call of callee whose Decl has these GNU C fn 
> attrs.
> 
> Perhaps when we de-indirect an indirect call to a direct call we don't carry 
> over the Metadata (unsure), but it's moot because the frontend didn't know to 
> attach the `dontcall` IR Fn attr because the frontend _cant_ de-indirect the 
> call.
> 
> So it's not a case that de-indirection in the backend drops the Metadata node 
> (though perhaps that's also an issue), moreso that the frontend didn't know 
> to attach the metadata in the first place because it only saw an indirect 
> call.
> 
> We could emit such Metadata for _all_ indirect calls from the frontend 
> (overkill), diagnose only when Debug Info is requested (not great), diagnose 
> but not provide line no of indirect call site (not great), simply not 
> diagnose (not great, but also unlikely IMO for there to be indirect calls of 
> such attributed functions), or maybe something else I'm not thinking of.  The 
> current implementation chooses to not diagnose.  Is that the best choice? 
> Definitely a clothespin vote.  Is there something better?  I was hoping you 
> all would tell me. :)
> The current implementation chooses to not diagnose. Is that the best choice?

I think it's a reasonable choice for the initial implementation. We can improve 
it later when we have a concrete use case. My primary concern was addressed 
though -- I'd rather have a false negative than a diagnostic with no source 
location information. The false negative is unfortunate, but IMO better than a 
frustrating diagnostic without source location information. The upside to the 
frustrating diagnostic is that we'd get a bug report about that (it's easier to 
miss the false negative and file a bug report about that). I suppose one way to 
address that is to use an assertion before the early return with a comment that 
the assertion is speculative rather than assertive. So in asserts builds we get 
a loud report and in other builds, we get the false negatives. WDYT?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106030/new/

https://reviews.llvm.org/D106030

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to