https://github.com/fmayer created https://github.com/llvm/llvm-project/pull/162939
This builtin can be used by user code to communicate with static analyis tools (e.g. clang-tidy or clang-static-analyzer). Because the arguments are unevaluated, it is suitable for use in macros, where evaluating the same expression multiple times can change program semantics. RFC: https://discourse.llvm.org/t/rfc-builtin-static-analysis-assume/88544 >From 8c84fe63aac839472e4dff7e5daca03c1cb4ab8f Mon Sep 17 00:00:00 2001 From: Florian Mayer <[email protected]> Date: Fri, 10 Oct 2025 16:08:14 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 --- clang/include/clang/Basic/Builtins.td | 6 +++++ clang/lib/CodeGen/CGBuiltin.cpp | 2 ++ .../test/AST/builtin-static-analysis-assume.c | 22 +++++++++++++++++++ .../CodeGen/builtin-static-analysis-assume.c | 17 ++++++++++++++ .../Sema/builtin-static-analysis-assume.cpp | 14 ++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 clang/test/AST/builtin-static-analysis-assume.c create mode 100644 clang/test/CodeGen/builtin-static-analysis-assume.c create mode 100644 clang/test/Sema/builtin-static-analysis-assume.cpp diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 792e2e07ec594..4f0e9129d98aa 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5253,3 +5253,9 @@ def CountedByRef : Builtin { let Attributes = [NoThrow, CustomTypeChecking]; let Prototype = "int(...)"; } + +def StaticAnalysisAssume : Builtin { + let Spellings = ["__builtin_static_analysis_assume"]; + let Attributes = [NoThrow, Const, Pure, UnevaluatedArguments]; + let Prototype = "void(bool)"; +} diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 9ee810c9d5775..34e6b512d20c6 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3733,6 +3733,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Result); } + case Builtin::BI__builtin_static_analysis_assume: + return RValue::get(nullptr); case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); // FIXME: Technically these constants should of type 'int', yes? diff --git a/clang/test/AST/builtin-static-analysis-assume.c b/clang/test/AST/builtin-static-analysis-assume.c new file mode 100644 index 0000000000000..ac544be49ab90 --- /dev/null +++ b/clang/test/AST/builtin-static-analysis-assume.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -ast-dump -triple x86_64-linux-gnu %s \ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK +// +// Tests with serialization: +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -include-pch %t -ast-dump-all /dev/null \ +// RUN: | FileCheck %s --strict-whitespace + +int fun() { + int x = 0; + __builtin_static_analysis_assume(++x >= 1); + return x; +} + +// CHECK: |-CallExpr {{.*}} <line:11:5, col:46> 'void' +// CHECK: | |-ImplicitCastExpr {{.*}} <col:5> 'void (*)(_Bool)' <BuiltinFnToFnPtr> +// CHECK: | | `-DeclRefExpr {{.*}} <col:5> '<builtin fn type>' Function {{.*}} '__builtin_static_analysis_assume' 'void (_Bool)' +// CHECK: | `-ImplicitCastExpr {{.*}} <col:38, col:45> '_Bool' <IntegralToBoolean> +// CHECK: | `-BinaryOperator {{.*}} <col:38, col:45> 'int' '>=' +// CHECK: | |-UnaryOperator {{.*}} <col:38, col:40> 'int' prefix '++' +// CHECK: | | `-DeclRefExpr {{.*}} <col:40> 'int' lvalue Var {{.*}} 'x' 'int' +// CHECK: | `-IntegerLiteral {{.*}} <col:45> 'int' 1 diff --git a/clang/test/CodeGen/builtin-static-analysis-assume.c b/clang/test/CodeGen/builtin-static-analysis-assume.c new file mode 100644 index 0000000000000..e73c2371be3b9 --- /dev/null +++ b/clang/test/CodeGen/builtin-static-analysis-assume.c @@ -0,0 +1,17 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix CHECK %s + +// CHECK-LABEL: define dso_local i32 @fun( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 0, ptr [[X]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int fun() { + int x = 0; + __builtin_static_analysis_assume(++x >= 1); + return x; +} diff --git a/clang/test/Sema/builtin-static-analysis-assume.cpp b/clang/test/Sema/builtin-static-analysis-assume.cpp new file mode 100644 index 0000000000000..3293e2ab15c55 --- /dev/null +++ b/clang/test/Sema/builtin-static-analysis-assume.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic + +void voidfn(); + +class Foo{}; + +int fun() { + int x = 0; + __builtin_static_analysis_assume(true); + __builtin_static_analysis_assume(x <= 0); + __builtin_static_analysis_assume(voidfn()); // expected-error{{cannot initialize a parameter of type 'bool' with an rvalue of type 'void}} + __builtin_static_analysis_assume(Foo()); // expected-error{{no viable conversion from 'Foo' to 'bool'}} + return x; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
