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

Doug Wyatt via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 15 10:33:35 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:

Without making any changes specific to these tests, they currently generate:

```
void catches() try {} catch (...) {} // expected-note {{function cannot be inferred 'nonblocking' because it throws or catches exceptions}}

void nb20() [[clang::nonblocking]] {
	catches(); // expected-warning {{'nonblocking' function must not call non-'nonblocking' function 'catches'}}
}

struct S {
    int x;
    S(int x) try : x(x) {} catch (...) {} // expected-note {{function cannot be inferred 'nonblocking' because it throws or catches exceptions}}
    S(double) : x((throw 3, 3)) {} // expected-note {{function cannot be inferred 'nonblocking' because it throws or catches exceptions}}
};

int badi(); // expected-note {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}}

struct A {
    int x = (throw 3, 3); // expected-note {{function cannot be inferred 'nonblocking' because it throws or catches exceptions}}
};

struct B {
    int y = badi(); // expected-note {{function cannot be inferred 'nonblocking' because it calls non-'nonblocking' function 'badi'}}
};

void f() [[clang::nonblocking]] {
    S s1(3);   // expected-warning {{'nonblocking' function must not call non-'nonblocking' function 'S::S'}}
    S s2(3.0); // expected-warning {{'nonblocking' function must not call non-'nonblocking' function 'S::S'}}
    A a;       // expected-warning {{'nonblocking' function must not call non-'nonblocking' function 'A::A'}}
    B b;       // expected-warning {{ 'nonblocking' function must not call non-'nonblocking' function 'B::B'}}
}
```

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


More information about the cfe-commits mailing list