Where should "contradictory" attributes be handled?

I have recently introduced an attribute for the realtime sanitizer, (hopefully) aptly named sanitize_realtime

I intend to introduce a second, which is nosanitize_realtime.

In C++ code, at least, it would make sense to attribute a function such that both attributes could be affixed:

__attribute__((no_sanitize("realtime")))
void process() [[clang::nonblocking]]

(nonblocking is a clang function effect that implies among other things that this function should be looked at by rtsan)

This seemingly contradictory combo should be valid in clang, and not throw a compilation error. One example this is useful would be temporarily disregarding a failure until a later date.

This will (naively) produce IR that looks somewhat like:

define void @process() #0 {
}

attributes #0 = { sanitize_realtime nosanitize_realtime}

My questions are:

  1. Should this combo be explicitly disallowed in LLVM IR, meaning that the frontend needs to sort out which option is appropriate and only affix one?
  2. If this should be disallowed in LLVM IR, could someone point me to an example of how to make these attributes mutually exclusive?

My prototype solution has clang attaching both attributes if appropriate, then the transform pass just disregards sanitize_realtime, as nosanitize has higher precedence. This seems to work, but I’m unsure of any written or unwritten rules on the matter.

Thanks for any advice.

I think it’s reasonable to say that those two attributes are incompatible and the combo is disallowed in IR. You can do that by documenting it in the LangRef and adding something like this to the IR verifier: llvm-project/llvm/lib/IR/Verifier.cpp at 50f4168e40790bd91123824ee338643ac18ccc0b · llvm/llvm-project · GitHub

Thanks @jayfoad ! That makes sense to me. I appreciate the link, saved me a lot of scavenger hunt time.