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 {{.*}} 'void' +// CHECK: | |-ImplicitCastExpr {{.*}} 'void (*)(_Bool)' +// CHECK: | | `-DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_static_analysis_assume' 'void (_Bool)' +// CHECK: | `-ImplicitCastExpr {{.*}} '_Bool' +// CHECK: | `-BinaryOperator {{.*}} 'int' '>=' +// CHECK: | |-UnaryOperator {{.*}} 'int' prefix '++' +// CHECK: | | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'x' 'int' +// CHECK: | `-IntegerLiteral {{.*}} '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; +}