[clang] nonblocking/nonallocating attributes: 2nd pass caller/callee analysis (PR #99656)

Doug Wyatt via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 16 12:18:24 PDT 2024


================
@@ -0,0 +1,256 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -std=c++20 -verify %s
+// These are in a separate file because errors (e.g. incompatible attributes) currently prevent
+// the FXAnalysis pass from running at all.
+
+// This diagnostic is re-enabled and exercised in isolation later in this file.
+#pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept"
+
+// --- CONSTRAINTS ---
+
+void nb1() [[clang::nonblocking]]
+{
+	int *pInt = new int; // expected-warning {{'nonblocking' function must not allocate or deallocate memory}}
+	delete pInt; // expected-warning {{'nonblocking' function must not allocate or deallocate memory}}
+}
+
+void nb2() [[clang::nonblocking]]
+{
+	static int global; // expected-warning {{'nonblocking' function must not have static locals}}
+}
+
+void nb3() [[clang::nonblocking]]
+{
+	try {
+		throw 42; // expected-warning {{'nonblocking' function must not throw or catch exceptions}}
+	}
+	catch (...) { // expected-warning {{'nonblocking' function must not throw or catch exceptions}}
+	}
+}
+
----------------
dougsonos wrote:

I looked into this a bit more deeply. Member initializers are one variant of a `CXXCtorInitializer`, and currently these are seen as part of the constructor itself, because the AST traversal of the constructor visits their expressions. So violations are attributed to the constructor(s) which use the member initializer, though the source location is correctly obtained from the problem initializer.

It looks like base class initializers and delegating initializers are already being traversed as true function calls. So it's only a normal field or anonymous field that would need special treatment.

If we wanted the language of the diagnostics to distinguish between the body of the constructor and its initializers, one approach would be to treat the initializers as if they were "callable", so that everything about the analysis's diagnostics would see them as "functions" that are "called' from the constructor -- though they'd have to be called "initializers" and not "functions."

That might be too general; a narrower approach would be to note the extra context of being inside an initializer when a violation is generated from a constructor, and add that context to the diagnostic.

https://github.com/llvm/llvm-project/pull/99656


More information about the cfe-commits mailing list