diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index 26fa7f33205eb..f1eb168a4ea9c 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -259,6 +259,6 @@ LangOptionsBase::getBoundsSafetyNewChecksMaskForGroup(StringRef GroupName) { LangOptionsBase::BoundsSafetyNewChecksMaskIntTy LangOptionsBase::getDefaultBoundsSafetyNewChecksMask() { - return BS_CHK_None; + return getBoundsSafetyNewChecksMaskForGroup("batch_0"); } /* TO_UPSTREAM(BoundsSafety) OFF*/ diff --git a/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/builtin-function-main.c b/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/builtin-function-main.c new file mode 100644 index 0000000000000..c2b1dafbfeb0a --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/builtin-function-main.c @@ -0,0 +1,312 @@ +#include +#include + +// RUN: %clang_cc1 -ast-dump -fbounds-safety %s -I %S/include | FileCheck %s --implicit-check-not "GetBoundExpr {{.+}} 'char *__single'" --implicit-check-not "GetBoundExpr {{.+}} 'char *'" +// RUN: %clang_cc1 -ast-dump -fbounds-safety %s -I %S/include -x objective-c -fbounds-attributes-objc-experimental | FileCheck %s --implicit-check-not "GetBoundExpr {{.+}} 'char *__single'" --implicit-check-not "GetBoundExpr {{.+}} 'char *'" + +char * __counted_by(len) func(char * __counted_by(len) src_str, int len) { + int len2 = 0; + char * __counted_by(len2) dst_str; + dst_str = __unsafe_forge_bidi_indexable(char*, malloc(len), len); + len2 = len; + memcpy(dst_str, src_str, len); + return dst_str; +} + +// CHECK: TranslationUnitDecl +// CHECK: |-FunctionDecl [[func_static:0x[^ ]+]] {{.+}} static +// CHECK: | |-ParmVarDecl [[var_dst:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_src:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | `-MaterializeSequenceExpr {{.+}} +// CHECK: | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | `-AssumptionExpr +// CHECK: | | | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: | | |-OpaqueValueExpr [[ove_1]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_dst]] +// CHECK: | | |-OpaqueValueExpr [[ove_2]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src]] +// CHECK: | | |-OpaqueValueExpr [[ove_3]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_size]] +// CHECK: | | `-OpaqueValueExpr [[ove]] +// CHECK: | | `-CallExpr +// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK: | | | `-DeclRefExpr {{.+}} +// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' +// CHECK: | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' +// CHECK: | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: | |-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' +// CHECK: | |-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' +// CHECK: | |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: | `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: |-FunctionDecl [[func_static_1:0x[^ ]+]] {{.+}} static +// CHECK: | |-ParmVarDecl [[var_dst_1:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_src_1:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size_1:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | `-ReturnStmt +// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | `-MaterializeSequenceExpr {{.+}} +// CHECK: | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | `-AssumptionExpr +// CHECK: | | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: | | |-OpaqueValueExpr [[ove_5]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_dst_1]] +// CHECK: | | |-OpaqueValueExpr [[ove_6]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_1]] +// CHECK: | | |-OpaqueValueExpr [[ove_7]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_size_1]] +// CHECK: | | `-OpaqueValueExpr [[ove_4]] +// CHECK: | | `-CallExpr +// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK: | | | `-DeclRefExpr {{.+}} +// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' +// CHECK: | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' +// CHECK: | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: | |-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' +// CHECK: | |-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' +// CHECK: | |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: | `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: |-FunctionDecl [[func_static_2:0x[^ ]+]] {{.+}} static +// CHECK: | |-ParmVarDecl [[var_dst_2:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_src_2:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size_2:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | |-DeclStmt +// CHECK: | | `-VarDecl [[var_tmp:0x[^ ]+]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'void *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | | `-AssumptionExpr +// CHECK: | | | | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: | | | |-OpaqueValueExpr [[ove_9]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_dst_2]] +// CHECK: | | | |-OpaqueValueExpr [[ove_10]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_2]] +// CHECK: | | | |-OpaqueValueExpr [[ove_11]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_size_2]] +// CHECK: | | | `-OpaqueValueExpr [[ove_8]] +// CHECK: | | | `-CallExpr +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK: | | | | `-DeclRefExpr {{.+}} +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' +// CHECK: | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' +// CHECK: | | |-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' +// CHECK: | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: | `-ReturnStmt +// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | `-DeclRefExpr {{.+}} [[var_tmp]] +// CHECK: |-FunctionDecl [[func_static_3:0x[^ ]+]] {{.+}} static +// CHECK: | |-ParmVarDecl [[var_size_3:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | `-ReturnStmt +// CHECK: | `-CallExpr +// CHECK: | |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' +// CHECK: | | `-DeclRefExpr {{.+}} +// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_size_3]] +// CHECK: |-FunctionDecl [[func_static_4:0x[^ ]+]] {{.+}} static +// CHECK: | |-ParmVarDecl [[var_size_4:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | |-DeclStmt +// CHECK: | | `-VarDecl [[var_tmp_1:0x[^ ]+]] +// CHECK: | | `-CallExpr +// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' +// CHECK: | | | `-DeclRefExpr {{.+}} +// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_size_4]] +// CHECK: | `-ReturnStmt +// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | `-DeclRefExpr {{.+}} [[var_tmp_1]] +// CHECK: `-FunctionDecl [[func_func:0x[^ ]+]] {{.+}} func +// CHECK: |-ParmVarDecl [[var_src_str:0x[^ ]+]] +// CHECK: |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK: | `-DependerDeclsAttr +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_len2:0x[^ ]+]] +// CHECK: | |-IntegerLiteral {{.+}} 0 +// CHECK: | `-DependerDeclsAttr +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_dst_str:0x[^ ]+]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsCheckExpr {{.+}} '((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) && __builtin_get_pointer_lower_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) <= ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && len <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) - ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && 0 <= len' +// CHECK: | | |-BinaryOperator {{.+}} 'char *__single __counted_by(len2)':'char *__single' '=' +// CHECK: | | | |-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-GetBoundExpr {{.+}} lower +// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: | | | |-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-IntegerLiteral {{.+}} 0 +// CHECK: | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: | |-OpaqueValueExpr [[ove_12]] +// CHECK: | | `-ParenExpr +// CHECK: | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | `-ForgePtrExpr +// CHECK: | | |-ParenExpr +// CHECK: | | | `-CallExpr +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *(*__single)(int)' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[func_static_3]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: | | |-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-ParenExpr +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: | `-OpaqueValueExpr [[ove_13]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BinaryOperator {{.+}} 'int' '=' +// CHECK: | | |-DeclRefExpr {{.+}} [[var_len2]] +// CHECK: | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: | |-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: |-CallExpr +// CHECK: | |-ImplicitCastExpr {{.+}} 'void (*__single)(void *restrict, void *restrict, int)' +// CHECK: | | `-DeclRefExpr {{.+}} [[func_static]] +// CHECK: | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | |-OpaqueValueExpr [[ove_14]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK: | | | `-OpaqueValueExpr [[ove_15]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len2]] +// CHECK: | | |-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | |-OpaqueValueExpr [[ove_16]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_str]] +// CHECK: | | | `-OpaqueValueExpr [[ove_17]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: | | |-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: `-ReturnStmt +// CHECK: `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' +// CHECK: | |-OpaqueValueExpr [[ove_18]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK: | `-OpaqueValueExpr [[ove_19]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_len2]] +// CHECK: |-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' diff --git a/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/include/builtin-function-sys.h b/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/include/builtin-function-sys.h new file mode 120000 index 0000000000000..da69a01147ac6 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/SystemHeaders/include/builtin-function-sys.h @@ -0,0 +1 @@ +../../../../BoundsSafety/AST/SystemHeaders/include/builtin-function-sys.h \ No newline at end of file diff --git a/clang/test/BoundsSafety/AST/bounds-attributed-in-return-disabled.c b/clang/test/BoundsSafety-legacy-checks/AST/bounds-attributed-in-return-disabled.c similarity index 98% rename from clang/test/BoundsSafety/AST/bounds-attributed-in-return-disabled.c rename to clang/test/BoundsSafety-legacy-checks/AST/bounds-attributed-in-return-disabled.c index 78c55972465d3..2d1780862d020 100644 --- a/clang/test/BoundsSafety/AST/bounds-attributed-in-return-disabled.c +++ b/clang/test/BoundsSafety-legacy-checks/AST/bounds-attributed-in-return-disabled.c @@ -5,7 +5,7 @@ #include -// TODO: Remove this test when return-size checks are enabled by default. +// TODO: Remove this test when support for disabling return-size checks is removed. // CHECK: FunctionDecl [[func_cb_in_from_bidi:0x[^ ]+]] {{.+}} cb_in_from_bidi // CHECK: |-ParmVarDecl [[var_count:0x[^ ]+]] diff --git a/clang/test/BoundsSafety-legacy-checks/AST/count-attrs.c b/clang/test/BoundsSafety-legacy-checks/AST/count-attrs.c new file mode 100644 index 0000000000000..c324433b97246 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/count-attrs.c @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s | FileCheck %s +#include + +int *__counted_by(len) frob(int len); + +int *__sized_by(len) byte_frob(int len); +void *alloc_bytes(int byte_count) __attribute__((alloc_size(1))); +// +// void *alloc_items(int byte_count, int size) __attribute__((alloc_size(1, 2))); + +typedef int (__array_decay_discards_count_in_parameters int_array_t)[10]; +void count_attr_in_bracket(int buf[__counted_by(len)], int len); +void count_ignored_from_array(int (__array_decay_discards_count_in_parameters buf)[10]); +void count_ignored_and_attr(int_array_t __counted_by(count) buf, int count); + +struct s { + int *__counted_by(l) bp; + int *bp2 __counted_by(l+1); + unsigned char *bp3 __sized_by(l); + unsigned char *bp4 __sized_by(l+1); + int l; +}; + +void test(void) { + int n = 0; + int *__counted_by(n) buf1; + int n2 = 0; + int *buf2 __counted_by(n2); + int n3 = sizeof(int) * n; + unsigned char *__sized_by(n3) byte_buf1; + int n4 = sizeof(int) * n2; + unsigned char *byte_buf2 __sized_by(n4); +} + +int *__counted_by(len) frob_body(int len) { return 0; } +int *__sized_by(len) byte_frob_body(int len) { return 0; } +// CHECK:TranslationUnitDecl {{.*}} +// CHECK:|-FunctionDecl {{.*}} frob 'int *__single __counted_by(len)(int)' +// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' +// CHECK-NEXT:|-FunctionDecl {{.*}} byte_frob 'int *__single __sized_by(len)(int)' +// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' +// CHECK-NEXT:|-FunctionDecl {{.*}} alloc_bytes 'void *__single(int)' +// CHECK-NEXT:| |-ParmVarDecl {{.*}} byte_count 'int' +// CHECK-NEXT:| `-AllocSizeAttr {{.*}} 1 +// CHECK-NEXT:|-TypedefDecl {{.*}} referenced int_array_t '__array_decay_discards_count_in_parameters int[10]':'int[10]' +// CHECK-NEXT:| `-MacroQualifiedType {{.*}} '__array_decay_discards_count_in_parameters int[10]' sugar +// CHECK-NEXT:| `-AttributedType {{.*}} 'int[10] __attribute__((decay_discards_count_in_parameters))' sugar +// CHECK-NEXT:| `-ParenType {{.*}} 'int[10]' sugar +// CHECK-NEXT:| `-ConstantArrayType {{.*}} 'int[10]' 10 +// CHECK-NEXT:| `-BuiltinType {{.*}} 'int' +// CHECK-NEXT:|-FunctionDecl {{.*}} count_attr_in_bracket 'void (int *__single __counted_by(len), int)' +// CHECK-NEXT:| |-ParmVarDecl {{.*}} buf 'int *__single __counted_by(len)':'int *__single' +// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' +// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:|-FunctionDecl {{.*}} count_ignored_from_array 'void (int *__single)' +// CHECK-NEXT:| `-ParmVarDecl {{.*}} buf 'int *__single' +// CHECK-NEXT:|-FunctionDecl {{.*}} count_ignored_and_attr 'void (int *__single __counted_by(count), int)' +// CHECK-NEXT:| |-ParmVarDecl {{.*}} buf 'int *__single __counted_by(count)':'int *__single' +// CHECK-NEXT:| `-ParmVarDecl {{.*}} used count 'int' +// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:|-RecordDecl {{.*}} struct s definition +// CHECK-NEXT:| |-FieldDecl {{.*}} bp 'int *__single __counted_by(l)':'int *__single' +// CHECK-NEXT:| |-FieldDecl {{.*}} bp2 'int *__single __counted_by(l + 1)':'int *__single' +// CHECK-NEXT:| |-FieldDecl {{.*}} bp3 'unsigned char *__single __sized_by(l)':'unsigned char *__single' +// CHECK-NEXT:| |-FieldDecl {{.*}} bp4 'unsigned char *__single __sized_by(l + 1)':'unsigned char *__single' +// CHECK-NEXT:| `-FieldDecl {{.*}} referenced l 'int' +// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} {{.*}} {{.*}} {{.*}} 0 0 0 0 +// CHECK-NEXT:|-FunctionDecl {{.*}} test 'void (void)' +// CHECK-NEXT:| `-CompoundStmt {{.*}} +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} used n 'int' cinit +// CHECK-NEXT:| | |-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} buf1 'int *__single __counted_by(n)':'int *__single' +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} used n2 'int' cinit +// CHECK-NEXT:| | |-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} buf2 'int *__single __counted_by(n2)':'int *__single' +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} used n3 'int' cinit +// CHECK-NEXT:| | |-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT:| | | `-BinaryOperator {{.*}} 'unsigned long' '*' +// CHECK-NEXT:| | | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'int' +// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'unsigned long' +// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT:| | | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'n' 'int' +// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} byte_buf1 'unsigned char *__single __sized_by(n3)':'unsigned char *__single' +// CHECK-NEXT:| |-DeclStmt {{.*}} +// CHECK-NEXT:| | `-VarDecl {{.*}} used n4 'int' cinit +// CHECK-NEXT:| | |-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT:| | | `-BinaryOperator {{.*}} 'unsigned long' '*' +// CHECK-NEXT:| | | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'int' +// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'unsigned long' +// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT:| | | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'n2' 'int' +// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 +// CHECK-NEXT:| `-DeclStmt {{.*}} +// CHECK-NEXT:| `-VarDecl {{.*}} byte_buf2 'unsigned char *__single __sized_by(n4)':'unsigned char *__single' +// CHECK-NEXT:|-FunctionDecl {{.*}} frob_body 'int *__single __counted_by(len)(int)' +// CHECK-NEXT:| |-ParmVarDecl {{.*}} used len 'int' +// CHECK-NEXT:| `-CompoundStmt {{.*}} +// CHECK-NEXT:| `-ReturnStmt {{.*}} +// CHECK-NEXT:| `-ImplicitCastExpr {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK-NEXT:| `-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT:`-FunctionDecl {{.*}} byte_frob_body 'int *__single __sized_by(len)(int)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} used len 'int' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/BoundsSafety-legacy-checks/AST/counted_by_or_null_call.c b/clang/test/BoundsSafety-legacy-checks/AST/counted_by_or_null_call.c new file mode 100644 index 0000000000000..9c06fd32203a8 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/counted_by_or_null_call.c @@ -0,0 +1,610 @@ +// RUN: %clang_cc1 -ast-dump -fbounds-safety -Wno-bounds-safety-init-list %s | FileCheck %s +// RUN: %clang_cc1 -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list %s | FileCheck %s + +#include + +// CHECK: {{^}}|-FunctionDecl [[func_foo:0x[^ ]+]] {{.+}} foo +// CHECK: {{^}}| |-ParmVarDecl [[var_p:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +void foo(int *__counted_by_or_null(len) p, int len) {} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_1:0x[^ ]+]] {{.+}} caller_1 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '0 <= 0 && 0 <= 0 && !0 || 2 <= 0 - 0 && 0 <= 2' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +void caller_1() { + foo(0, 2); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_2:0x[^ ]+]] {{.+}} caller_2 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '0 <= 0 && 0 <= 0 && !0 || 0 <= 0 - 0 && 0 <= 0' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +void caller_2() { + foo(0, 0); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] +// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +void caller_3(int *__counted_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| |-DeclStmt +// CHECK: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= -1' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] +// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_9]] +// CHECK: {{^}}| | `-UnaryOperator {{.+}} prefix '-' +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 1 +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| |-DeclStmt +// CHECK: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= 2' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] +// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_11]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] +// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +void caller_6(int *__counted_by(len) p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_17]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_19]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +void caller_8(int *__single p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_bar:0x[^ ]+]] {{.+}} bar +// CHECK: {{^}}| |-ParmVarDecl [[var_out:0x[^ ]+]] +// CHECK: {{^}}| `-ParmVarDecl [[var_len_5:0x[^ ]+]] +// CHECK: {{^}}| `-DependerDeclsAttr +void bar(int *__counted_by(*len) *out, int *len); + +// CHECK: {{^}}|-FunctionDecl [[func_caller_9:0x[^ ]+]] {{.+}} caller_9 +// CHECK: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-CallExpr +// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_21]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' +void caller_9(int *__counted_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 +// CHECK: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] +// CHECK: {{^}} `-CompoundStmt +// CHECK: {{^}} |-DeclStmt +// CHECK: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] +// CHECK: {{^}} | `-DependerDeclsAttr +// CHECK: {{^}} |-DeclStmt +// CHECK: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | |-CallExpr +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' +// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] +// CHECK: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_23]] +// CHECK: {{^}} | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' '=' +// CHECK: {{^}} | | | |-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} lower +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}} | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} upper +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] +// CHECK: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25]] +// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_26]] +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] +// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_len_7]] +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BinaryOperator {{.+}} 'int' '=' +// CHECK: {{^}} | | |-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} `-ReturnStmt +// CHECK: {{^}} `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}} `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_28:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_29:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_28]] +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_29]] +// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} |-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_29]] {{.*}} 'int' +int *__counted_by_or_null(len) caller_10(int len) { + int count; + int *__counted_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} diff --git a/clang/test/BoundsSafety-legacy-checks/AST/ended_by_const_param.c b/clang/test/BoundsSafety-legacy-checks/AST/ended_by_const_param.c new file mode 100644 index 0000000000000..a0decc6a9fdfb --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/ended_by_const_param.c @@ -0,0 +1,91 @@ +// FileCheck lines automatically generated using make-ast-dump-check-v2.py + +// RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s 2>&1 | FileCheck %s +#include + +struct S { + int *end; + int *__ended_by(end) iter; +}; + +// CHECK-LABEL:|-FunctionDecl {{.+}} used foo 'void (int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' +// CHECK-NEXT: | |-ParmVarDecl {{.+}} used start 'int *__single __ended_by(end)const':'int *__singleconst' +// CHECK-NEXT: | |-ParmVarDecl {{.+}} used end 'int *__single /* __started_by(start) */ const':'int *__singleconst' +// CHECK-NEXT: | `-CompoundStmt {{.+}} +// CHECK-NEXT: | `-DeclStmt {{.+}} +// CHECK-NEXT: | `-VarDecl {{.+}} local 'int *__bidi_indexable' cinit +// CHECK-NEXT: | `-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | |-DeclRefExpr {{.+}} 'int *__single /* __started_by(start) */ const':'int *__singleconst' lvalue ParmVar {{.+}} 'end' 'int *__single /* __started_by(start) */ const':'int *__singleconst' +// CHECK-NEXT: | |-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(start) */ const':'int *__singleconst' +// CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int *__single /* __started_by(start) */ const':'int *__singleconst' lvalue ParmVar {{.+}} 'end' 'int *__single /* __started_by(start) */ const':'int *__singleconst' +// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} <> 'int *__single __ended_by(end)const':'int *__singleconst' +// CHECK-NEXT: | `-DeclRefExpr {{.+}} <> 'int *__single __ended_by(end)const':'int *__singleconst' lvalue ParmVar {{.+}} 'start' 'int *__single __ended_by(end)const':'int *__singleconst' +void foo(int * const __ended_by(end) start, int* const end) { + int *local = end; +} + +// CHECK-LABEL:`-FunctionDecl {{.+}} bar 'void (void)' +// CHECK-NEXT: `-CompoundStmt {{.+}} +// CHECK-NEXT: |-DeclStmt {{.+}} +// CHECK-NEXT: | `-VarDecl {{.+}} used arr 'int[40]' +// CHECK-NEXT: `-MaterializeSequenceExpr {{.+}} 'void' +// CHECK-NEXT: |-MaterializeSequenceExpr {{.+}} 'void' +// CHECK-NEXT: | |-BoundsCheckExpr {{.+}} 'void' 'arr + 40 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 40' +// CHECK-NEXT: | | |-CallExpr {{.+}} 'void' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'void (int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' Function {{.+}} 'foo' 'void (int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *__single __ended_by(end)':'int *__single' +// CHECK-NEXT: | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(start) */ ':'int *__single' +// CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | `-GetBoundExpr {{.+}} 'int *__bidi_indexable' upper +// CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: | |-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: |-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: `-IntegerLiteral {{.+}} 'int' 40 +void bar(void) { + int arr[40]; + foo(arr, arr + 40); +} diff --git a/clang/test/BoundsSafety-legacy-checks/AST/ended_by_returns.c b/clang/test/BoundsSafety-legacy-checks/AST/ended_by_returns.c new file mode 100644 index 0000000000000..2665227c8b9ce --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/ended_by_returns.c @@ -0,0 +1,492 @@ +// RUN: %clang_cc1 -ast-dump -fbounds-safety %s 2> /dev/null | FileCheck %s +// RUN: %clang_cc1 -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s 2> /dev/null | FileCheck %s + +#include + +char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { + return begin + 1; +} +//CHECK: FunctionDecl [[func_chunk:0x[^ ]+]] {{.*}} used chunk 'char *__single __ended_by(end)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +//CHECK: |-ParmVarDecl [[var_begin:0x[^ ]+]] {{.*}} 'char *__single __ended_by(end)':'char *__single' +//CHECK: |-ParmVarDecl [[var_end:0x[^ ]+]] {{.*}} 'char *__single /* __started_by(begin) */ ':'char *__single' +//CHECK: `-CompoundStmt +//CHECK: `-ReturnStmt +//CHECK: `-ImplicitCastExpr {{.*}} 'char *__single __ended_by(end)':'char *__single' +//CHECK: `-BinaryOperator {{.*}} 'char *__bidi_indexable' '+' +//CHECK: |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +//CHECK: | |-DeclRefExpr {{.+}} [[var_begin]] +//CHECK: | |-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +//CHECK: | | `-DeclRefExpr {{.+}} [[var_end]] +//CHECK: | `-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +//CHECK: | `-DeclRefExpr {{.+}} [[var_begin]] +//CHECK: `-IntegerLiteral {{.*}} 'int' 1 + +// CHECK-LABEL: foo +void foo(void) { + int arr[10]; + int *p = chunk(arr, arr+10); +} +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr:0x[^ ]+]] +// CHECK: `-DeclStmt +// CHECK: `-VarDecl [[var_p:0x[^ ]+]] +// CHECK: `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | |-BoundsCheckExpr +// CHECK: | | | |-CallExpr +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr]] +// CHECK: | `-OpaqueValueExpr [[ove_1]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr]] +// CHECK: | `-IntegerLiteral {{.+}} 10 +// CHECK: |-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' + +// CHECK-LABEL: fooCast +void fooCast(void) { + int arr[10]; + int *p = (int*)chunk(arr, arr+10); +} +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr_1:0x[^ ]+]] +// CHECK: `-DeclStmt +// CHECK: `-VarDecl [[var_p_1:0x[^ ]+]] +// CHECK: `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | |-BoundsCheckExpr +// CHECK: | | | |-CallExpr +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_2]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_1]] +// CHECK: | `-OpaqueValueExpr [[ove_3]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_1]] +// CHECK: | `-IntegerLiteral {{.+}} 10 +// CHECK: |-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' + +struct DataWithEndedBy { + int *__ended_by(fend) fbegin; + int *fend; +}; + +// CHECK-LABEL: bar +void bar(struct DataWithEndedBy *data) { + int arr[10]; + data->fbegin = chunk(arr, arr+10); + data->fend = arr+10; +} +// CHECK: |-ParmVarDecl [[var_data:0x[^ ]+]] +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr_2:0x[^ ]+]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsCheckExpr +// CHECK: | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' +// CHECK: | | | |-MemberExpr {{.+}} ->fbegin +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-GetBoundExpr {{.+}} lower +// CHECK: | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_4]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-BoundsCheckExpr +// CHECK: | | | | | |-CallExpr +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_5]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK: | | | `-OpaqueValueExpr [[ove_6]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK: | | | `-IntegerLiteral {{.+}} 10 +// CHECK: | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | `-OpaqueValueExpr [[ove_7]] +// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK: | `-IntegerLiteral {{.+}} 10 +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' +// CHECK: | |-MemberExpr {{.+}} ->fend +// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_data]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' +// CHECK: | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' +// CHECK: |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' + +// CHECK-LABEL: barCast +void barCast(struct DataWithEndedBy *data) { + int arr[10]; + data->fbegin = (int*)chunk(arr, arr+10); + data->fend = arr+10; +} +// CHECK: |-ParmVarDecl [[var_data_1:0x[^ ]+]] +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr_3:0x[^ ]+]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsCheckExpr +// CHECK: | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' +// CHECK: | | | |-MemberExpr {{.+}} ->fbegin +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_1]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-GetBoundExpr {{.+}} lower +// CHECK: | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_8]] +// CHECK: | | `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-BoundsCheckExpr +// CHECK: | | | | | |-CallExpr +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_9]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK: | | | `-OpaqueValueExpr [[ove_10]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK: | | | `-IntegerLiteral {{.+}} 10 +// CHECK: | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' +// CHECK: | `-OpaqueValueExpr [[ove_11]] +// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK: | `-IntegerLiteral {{.+}} 10 +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' +// CHECK: | |-MemberExpr {{.+}} ->fend +// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_1]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' +// CHECK: | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' +// CHECK: |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' + +struct DataWithCountedBy { + long *__counted_by(count) ptr; + unsigned long long count; +}; + +// CHECK-LABEL: baz 'void (struct DataWithCountedBy *__single, int)' +void baz(struct DataWithCountedBy *data, int len) { + int arr[10]; + data->ptr = chunk(arr, arr+10); + data->count = len; +} +// CHECK: |-ParmVarDecl [[var_data_2:0x[^ ]+]] +// CHECK: |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr_4:0x[^ ]+]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsCheckExpr +// CHECK: | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' +// CHECK: | | | |-MemberExpr {{.+}} ->ptr +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_2]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-GetBoundExpr {{.+}} lower +// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'unsigned long long' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK: | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: | | |-GetBoundExpr {{.+}} upper +// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_12]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-BoundsCheckExpr +// CHECK: | | | | | |-CallExpr +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_13]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] +// CHECK: | | | `-OpaqueValueExpr [[ove_14]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] +// CHECK: | | | `-IntegerLiteral {{.+}} 10 +// CHECK: | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' +// CHECK: | `-OpaqueValueExpr [[ove_15]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-BinaryOperator {{.+}} 'unsigned long long' '=' +// CHECK: | |-MemberExpr {{.+}} ->count +// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_2]] +// CHECK: | `-OpaqueValueExpr [[ove_15]] {{.*}} 'unsigned long long' +// CHECK: |-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_15]] {{.*}} 'unsigned long long' + +// CHECK-LABEL: bazCast 'void (struct DataWithCountedBy *__single, int)' +void bazCast(struct DataWithCountedBy *data, int len) { + int arr[10]; + data->ptr = (long*)chunk(arr, arr+10); + data->count = len; +} +// CHECK: |-ParmVarDecl [[var_data_3:0x[^ ]+]] +// CHECK: |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK: `-CompoundStmt +// CHECK: |-DeclStmt +// CHECK: | `-VarDecl [[var_arr_5:0x[^ ]+]] +// CHECK: |-MaterializeSequenceExpr {{.+}} +// CHECK: | |-BoundsCheckExpr +// CHECK: | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' +// CHECK: | | | |-MemberExpr {{.+}} ->ptr +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_3]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-GetBoundExpr {{.+}} lower +// CHECK: | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'unsigned long long' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK: | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: | | |-GetBoundExpr {{.+}} upper +// CHECK: | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK: | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_16]] +// CHECK: | | `-CStyleCastExpr {{.+}} 'long *__bidi_indexable' +// CHECK: | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | |-BoundsCheckExpr +// CHECK: | | | | | |-CallExpr +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_17]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] +// CHECK: | | | `-OpaqueValueExpr [[ove_18]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] +// CHECK: | | | `-IntegerLiteral {{.+}} 10 +// CHECK: | | |-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: | `-OpaqueValueExpr [[ove_19]] +// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK: `-MaterializeSequenceExpr {{.+}} +// CHECK: |-BinaryOperator {{.+}} 'unsigned long long' '=' +// CHECK: | |-MemberExpr {{.+}} ->count +// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_3]] +// CHECK: | `-OpaqueValueExpr [[ove_19]] {{.*}} 'unsigned long long' +// CHECK: |-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' +// CHECK: `-OpaqueValueExpr [[ove_19]] {{.*}} 'unsigned long long' diff --git a/clang/test/BoundsSafety-legacy-checks/AST/sized_by_or_null_call.c b/clang/test/BoundsSafety-legacy-checks/AST/sized_by_or_null_call.c new file mode 100644 index 0000000000000..67041132b2d28 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/sized_by_or_null_call.c @@ -0,0 +1,637 @@ +// RUN: %clang_cc1 -ast-dump -fbounds-safety -Wno-bounds-safety-init-list %s | FileCheck %s +// RUN: %clang_cc1 -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list %s | FileCheck %s + +#include + +// CHECK: {{^}}|-FunctionDecl [[func_foo:0x[^ ]+]] {{.+}} foo +// CHECK: {{^}}| |-ParmVarDecl [[var_p:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +void foo(int *__sized_by_or_null(len) p, int len) {} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_1:0x[^ ]+]] {{.+}} caller_1 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '0 <= 0 && 0 <= 0 && !0 || 2 <= (char *)0 - (char *)0 && 0 <= 2' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-CStyleCastExpr {{.+}} 'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_1]] {{.*}} 'int' +void caller_1() { + foo(0, 2); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_2:0x[^ ]+]] {{.+}} caller_2 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '0 <= 0 && 0 <= 0 && !0 || 0 <= (char *)0 - (char *)0 && 0 <= 0' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-CStyleCastExpr {{.+}} 'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +void caller_2() { + foo(0, 0); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] +// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +void caller_3(int *__sized_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| |-DeclStmt +// CHECK: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= -1' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] +// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_9]] +// CHECK: {{^}}| | `-UnaryOperator {{.+}} prefix '-' +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 1 +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| |-DeclStmt +// CHECK: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= 2' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] +// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_11]] +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] +// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +void caller_6(int *__sized_by(len) p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_17]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 +// CHECK: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK: {{^}}| | | |-CallExpr +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_19]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +void caller_8(int *__single p, int len) { + foo(p, len); +} + +// CHECK: {{^}}|-FunctionDecl [[func_bar:0x[^ ]+]] {{.+}} bar +// CHECK: {{^}}| |-ParmVarDecl [[var_out:0x[^ ]+]] +// CHECK: {{^}}| `-ParmVarDecl [[var_len_5:0x[^ ]+]] +// CHECK: {{^}}| `-DependerDeclsAttr +void bar(int *__sized_by(*len) *out, int *len); + +// CHECK: {{^}}|-FunctionDecl [[func_caller_9:0x[^ ]+]] {{.+}} caller_9 +// CHECK: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] +// CHECK: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] +// CHECK: {{^}}| | `-DependerDeclsAttr +// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}}| | |-CallExpr +// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' +// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_21]] +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' +void caller_9(int *__sized_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 +// CHECK: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] +// CHECK: {{^}} `-CompoundStmt +// CHECK: {{^}} |-DeclStmt +// CHECK: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] +// CHECK: {{^}} | `-DependerDeclsAttr +// CHECK: {{^}} |-DeclStmt +// CHECK: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | |-CallExpr +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' +// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] +// CHECK: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_23]] +// CHECK: {{^}} | | `-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *__bidi_indexable)p && 0 <= len' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' '=' +// CHECK: {{^}} | | | |-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} lower +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK: {{^}} | | |-UnaryOperator {{.+}} cannot overflow +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: {{^}} | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: {{^}} | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: {{^}} | | |-IntegerLiteral {{.+}} 0 +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] +// CHECK: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: {{^}} | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: {{^}} | | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25]] +// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_26]] +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] +// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_len_7]] +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BinaryOperator {{.+}} 'int' '=' +// CHECK: {{^}} | | |-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} `-ReturnStmt +// CHECK: {{^}} `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}} `-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK: {{^}} | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_28:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK: {{^}} | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_29:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_28]] +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_29]] +// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK: {{^}} |-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_29]] {{.*}} 'int' +int *__sized_by_or_null(len) caller_10(int len) { + int count; + int *__sized_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} + diff --git a/clang/test/BoundsSafety-legacy-checks/AST/unify-function-types.c b/clang/test/BoundsSafety-legacy-checks/AST/unify-function-types.c new file mode 100644 index 0000000000000..9d5cba3e408f6 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/AST/unify-function-types.c @@ -0,0 +1,260 @@ + +// RUN: %clang_cc1 -ast-dump -fbounds-safety -verify=c %s | FileCheck %s +// RUN: %clang_cc1 -x c++ -ast-dump -fbounds-safety -fbounds-attributes-cxx-experimental -verify=cpp %s +#include + +char funcA(char buf[__counted_by(len)], int len, int len2); +char funcB(char arr[__counted_by(size)], int size, int size2); +char funcC(char arr[__counted_by(size2)], int size, int size2); + +// CHECK: TranslationUnitDecl +// CHECK: |-FunctionDecl [[func_funcA:0x[^ ]+]] {{.+}} funcA +// CHECK: | |-ParmVarDecl [[var_buf:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | `-ParmVarDecl [[var_len2:0x[^ ]+]] +// CHECK: |-FunctionDecl [[func_funcB:0x[^ ]+]] {{.+}} funcB +// CHECK: | |-ParmVarDecl [[var_arr:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | `-ParmVarDecl [[var_size2:0x[^ ]+]] +// CHECK: |-FunctionDecl [[func_funcC:0x[^ ]+]] {{.+}} funcC +// CHECK: | |-ParmVarDecl [[var_arr_1:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size_1:0x[^ ]+]] +// CHECK: | `-ParmVarDecl [[var_size2_1:0x[^ ]+]] +// CHECK: | `-DependerDeclsAttr + +char test1(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + return (src_len % 2 == 0 ? funcA : funcB)(src_buf, src_len, src_len2); +} + +// CHECK: |-FunctionDecl [[func_test1:0x[^ ]+]] {{.+}} test1 +// CHECK: | |-ParmVarDecl [[var_src_buf:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_src_len:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | |-ParmVarDecl [[var_src_len2:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | `-ReturnStmt +// CHECK: | `-MaterializeSequenceExpr {{.+}} +// CHECK: | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-BoundsCheckExpr +// CHECK: | | | |-CallExpr +// CHECK: | | | | |-ParenExpr +// CHECK: | | | | | `-ConditionalOperator {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '==' +// CHECK: | | | | | | |-BinaryOperator {{.+}} 'int' '%' +// CHECK: | | | | | | | |-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK: | | | | | | | `-IntegerLiteral {{.+}} 2 +// CHECK: | | | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' +// CHECK: | | | | | | `-DeclRefExpr {{.+}} [[func_funcA]] +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(size), int, int)' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_funcB]] +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | |-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | | |-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-GetBoundExpr {{.+}} lower +// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: | | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-IntegerLiteral {{.+}} 0 +// CHECK: | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: | | |-OpaqueValueExpr [[ove]] +// CHECK: | | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' +// CHECK: | | | | |-OpaqueValueExpr [[ove_1]] +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[var_src_buf]] +// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK: | | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' +// CHECK: | | |-OpaqueValueExpr [[ove_3]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK: | | `-OpaqueValueExpr [[ove_4]] +// CHECK: | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | `-DeclRefExpr {{.+}} [[var_src_len2]] +// CHECK: | |-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int' + + +char test2(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + // c-error@+2{{conditional expression evaluates functions with incompatible bound attributes 'char (*__single)(char *__single __counted_by(len), int, int)' (aka 'char (*__single)(char *__single, int, int)') and 'char (*__single)(char *__single __counted_by(size2), int, int)' (aka 'char (*__single)(char *__single, int, int)')}} + // cpp-error@+1{{conditional expression evaluates functions with incompatible bound attributes 'char (char *__single __counted_by(len), int, int)' (aka 'char (char *__single, int, int)') and 'char (char *__single __counted_by(size2), int, int)' (aka 'char (char *__single, int, int)')}} + return (src_len % 2 == 0 ? funcA : funcC)(src_buf, src_len, src_len2); +} + +char * __counted_by(len) funcD(char buf[__counted_by(len)], int len, int len2); +char * __counted_by(size) funcE(char arr[__counted_by(size)], int size, int size2); +char * __counted_by(size2) funcF(char arr[__counted_by(size)], int size, int size2); + +// CHECK: |-FunctionDecl [[func_funcD:0x[^ ]+]] {{.+}} funcD +// CHECK: | |-ParmVarDecl [[var_buf_1:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | `-ParmVarDecl [[var_len2_1:0x[^ ]+]] +// CHECK: |-FunctionDecl [[func_funcE:0x[^ ]+]] {{.+}} funcE +// CHECK: | |-ParmVarDecl [[var_arr_2:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size_2:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | `-ParmVarDecl [[var_size2_2:0x[^ ]+]] +// CHECK: |-FunctionDecl [[func_funcF:0x[^ ]+]] {{.+}} funcF +// CHECK: | |-ParmVarDecl [[var_arr_3:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_size_3:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | `-ParmVarDecl [[var_size2_3:0x[^ ]+]] + +char * __counted_by(src_len) test3(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + return (src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2); +} + +// CHECK: |-FunctionDecl [[func_test3:0x[^ ]+]] {{.+}} test3 +// CHECK: | |-ParmVarDecl [[var_src_buf_2:0x[^ ]+]] +// CHECK: | |-ParmVarDecl [[var_src_len_2:0x[^ ]+]] +// CHECK: | | `-DependerDeclsAttr +// CHECK: | |-ParmVarDecl [[var_src_len2_2:0x[^ ]+]] +// CHECK: | `-CompoundStmt +// CHECK: | `-ReturnStmt +// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | `-MaterializeSequenceExpr {{.+}} +// CHECK: | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | | | | | |-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | | | |-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int' +// CHECK: | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: | | |-OpaqueValueExpr [[ove_6]] +// CHECK: | | | `-MaterializeSequenceExpr {{.+}} +// CHECK: | | | |-MaterializeSequenceExpr {{.+}} +// CHECK: | | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK: | | | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int' +// CHECK: | | | | |-OpaqueValueExpr [[ove_7]] +// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[var_src_buf_2]] +// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK: | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int' +// CHECK: | | |-OpaqueValueExpr [[ove_9]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK: | | |-OpaqueValueExpr [[ove_10]] +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len2_2]] +// CHECK: | | `-OpaqueValueExpr [[ove_5]] +// CHECK: | | `-BoundsCheckExpr +// CHECK: | | |-CallExpr +// CHECK: | | | |-ParenExpr +// CHECK: | | | | `-ConditionalOperator {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' +// CHECK: | | | | |-BinaryOperator {{.+}} 'int' '==' +// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '%' +// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'int' +// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK: | | | | | | `-IntegerLiteral {{.+}} 2 +// CHECK: | | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' +// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_funcD]] +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(size)(*__single)(char *__single __counted_by(size), int, int)' +// CHECK: | | | | `-DeclRefExpr {{.+}} [[func_funcE]] +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-GetBoundExpr {{.+}} lower +// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK: | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | | `-GetBoundExpr {{.+}} upper +// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK: | | |-IntegerLiteral {{.+}} 0 +// CHECK: | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: | |-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' +// CHECK: | |-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: | |-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__single __counted_by(len)':'char *__single' + +char test4(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + // c-error@+2{{conditional expression evaluates functions with incompatible bound attributes 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' (aka 'char *__single(*__single)(char *__single, int, int)') and 'char *__single __counted_by(size2)(*__single)(char *__single __counted_by(size), int, int)' (aka 'char *__single(*__single)(char *__single, int, int)')}} + // cpp-error@+1{{conditional expression evaluates functions with incompatible bound attributes 'char *__single __counted_by(len)(char *__single __counted_by(len), int, int)' (aka 'char *__single(char *__single, int, int)') and 'char *__single __counted_by(size2)(char *__single __counted_by(size), int, int)' (aka 'char *__single(char *__single, int, int)')}} + return *(src_len % 2 == 0 ? funcD : funcF)(src_buf, src_len, src_len2); +} + +#ifdef __cplusplus +char * __counted_by(src_len) test5(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + auto &funcRefD (funcD); + auto &funcRefE (funcE); + return (src_len % 2 == 0 ? funcRefD : funcRefE)(src_buf, src_len, src_len2); +} + +char * __counted_by(src_len) test6(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { + auto &funcRefD (funcD); + auto &funcRefF (funcF); + // cpp-error@+1{{conditional expression evaluates functions with incompatible bound attributes 'char *__single __counted_by(len)(char *__single __counted_by(len), int, int)' (aka 'char *__single(char *__single, int, int)') and 'char *__single __counted_by(size2)(char *__single __counted_by(size), int, int)' (aka 'char *__single(char *__single, int, int)')}} + return (src_len % 2 == 0 ? funcRefD : funcRefF)(src_buf, src_len, src_len2); +} + +#endif diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem-O2.c new file mode 100644 index 0000000000000..a94ffc9b0d1ac --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem-O2.c @@ -0,0 +1,32 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +int arr[10]; + +int v; + +int main() { + int *ptr = &arr[v]; + return *ptr; +} + +// CHECK-LABEL: @v +// CHECK-LABEL: @arr +// CHECK-LABEL: @main( +// CHECK: entry: +// CHECK: [[TMP0:%.*]] = load i32, ptr @v, align 4, {{!tbaa ![0-9]+}} +// CHECK: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr @arr, i64 [[IDXPROM]] +// CHECK: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], getelementptr inbounds nuw (i8, ptr @arr, i64 40), {{!annotation ![0-9]+}} +// CHECK: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], @arr, {{!annotation ![0-9]+}} +// CHECK: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK: unreachable +// CHECK: cont1: +// CHECK: [[TMP3:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} +// CHECK: ret i32 [[TMP3]] +// diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem.c new file mode 100644 index 0000000000000..e2cd4b12086c5 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-array-elem.c @@ -0,0 +1,63 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +int arr[10]; + +int v; + +// CHECK-LABEL: @main( +// CHECK: entry: +// CHECK: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK: store i32 0, ptr [[RETVAL]], align 4 +// CHECK: [[TMP0:%.*]] = load i32, ptr @v, align 4 +// CHECK: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK: store ptr @arr, ptr [[TMP1]], align 8 +// CHECK: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK: store ptr getelementptr inbounds (i32, ptr @arr, i64 10), ptr [[TMP2]], align 8 +// CHECK: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK: store ptr @arr, ptr [[TMP3]], align 8 +// CHECK: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 [[IDXPROM]] +// CHECK: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK: unreachable +// CHECK: cont: +// CHECK: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK: unreachable +// CHECK: cont2: +// CHECK: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK: ret i32 [[TMP15]] +// +int main() { + int *ptr = &arr[v]; + return *ptr; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-packed-struct.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-packed-struct.c new file mode 100644 index 0000000000000..ac2b39b8f29fd --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/addr-of-packed-struct.c @@ -0,0 +1,22 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +struct __attribute__((packed)) foo { + char x; // field 0 + short s; // field 1 + // : field 2 + unsigned __attribute__((aligned(4))) u; // field 3 +}; + +// CHECK-LABEL: @p( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[S:%.*]], i64 4 +// CHECK-NEXT: ret ptr [[TMP0]] +// +unsigned *p(struct foo *s) { + return &s->u; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/addrof-member-to-single-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/addrof-member-to-single-O2.c new file mode 100644 index 0000000000000..b1a637bed382e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/addrof-member-to-single-O2.c @@ -0,0 +1,191 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple arm64e-apple-iphoneos %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64e-apple-iphoneos %s -o - | FileCheck %s + +#include + +struct foo { + char *ptr; + int i; + long l; +}; + +// CHECK-LABEL: @addrof_single_ptr_to_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret ptr [[F:%.*]] +// +char **addrof_single_ptr_to_single(struct foo *f) { + return &f->ptr; +} + +// CHECK-LABEL: @addrof_single_i_to_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F:%.*]], i64 8 +// CHECK-NEXT: ret ptr [[TMP0]] +// +int *addrof_single_i_to_single(struct foo *f) { + return &f->i; +} + +// CHECK-LABEL: @addrof_single_l_to_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F:%.*]], i64 16 +// CHECK-NEXT: ret ptr [[TMP0]] +// +long *addrof_single_l_to_single(struct foo *f) { + return &f->l; +} + +static inline char **__addrof_bidi_ptr_to_single(struct foo *__bidi_indexable f) { + return &f->ptr; +} + +// CHECK-LABEL: @addrof_bidi_ptr_to_single( +// CHECK-NEXT: __addrof_bidi_ptr_to_single.exit: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: ret ptr [[F]] +// +char **addrof_bidi_ptr_to_single(void) { + struct foo f; + return __addrof_bidi_ptr_to_single(&f); +} + +// CHECK-LABEL: @addrof_bidi_ptr_to_single_oob_upper( +// CHECK-NEXT: trap.i: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +char **addrof_bidi_ptr_to_single_oob_upper(void) { + struct foo f; + struct foo *fp = &f + 1; + return __addrof_bidi_ptr_to_single(fp); +} + + +// CHECK-LABEL: @addrof_bidi_ptr_to_single_oob_lower( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6:[0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_PTR_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap.i: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: __addrof_bidi_ptr_to_single.exit: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: ret ptr [[BOUND_PTR_ARITH]] +// +char **addrof_bidi_ptr_to_single_oob_lower(void) { + struct foo f; + struct foo *fp = &f - 1; + return __addrof_bidi_ptr_to_single(fp); +} + +static inline int *__addrof_bidi_i_to_single(struct foo *__bidi_indexable f) { + return &f->i; +} + +// CHECK-LABEL: @addrof_bidi_i_to_single( +// CHECK-NEXT: __addrof_bidi_i_to_single.exit: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 8 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: ret ptr [[TMP0]] +// +int *addrof_bidi_i_to_single(void) { + struct foo f; + return __addrof_bidi_i_to_single(&f); +} + +// CHECK-LABEL: @addrof_bidi_i_to_single_oob_upper( +// CHECK-NEXT: trap.i: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +int *addrof_bidi_i_to_single_oob_upper(void) { + struct foo f; + struct foo *fp = &f+1; + return __addrof_bidi_i_to_single(fp); +} + +// CHECK-LABEL: @addrof_bidi_i_to_single_oob_lower( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_I_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap.i: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: __addrof_bidi_i_to_single.exit: +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[F]], i64 -16 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: ret ptr [[TMP3]] +// +int *addrof_bidi_i_to_single_oob_lower(void) { + struct foo f; + struct foo *fp = &f-1; + return __addrof_bidi_i_to_single(fp); +} + +static inline long *__addrof_bidi_l_to_single(struct foo *__bidi_indexable f) { + return &f->l; +} + +// CHECK-LABEL: @addrof_bidi_l_to_single( +// CHECK-NEXT: __addrof_bidi_l_to_single.exit: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 16 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: ret ptr [[TMP0]] +// +long *addrof_bidi_l_to_single(void) { + struct foo f; + return __addrof_bidi_l_to_single(&f); +} + +// CHECK-LABEL: @addrof_bidi_l_to_single_oob_upper( +// CHECK-NEXT: trap.i: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +long *addrof_bidi_l_to_single_oob_upper(void) { + struct foo f; + struct foo *fp = &f+1; + return __addrof_bidi_l_to_single(fp); +} + +// CHECK-LABEL: @addrof_bidi_l_to_single_oob_lower( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_L_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap.i: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: __addrof_bidi_l_to_single.exit: +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[F]], i64 -8 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: ret ptr [[TMP3]] +// +long *addrof_bidi_l_to_single_oob_lower(void) { + struct foo f; + struct foo *fp = &f-1; + return __addrof_bidi_l_to_single(fp); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c new file mode 100644 index 0000000000000..dab393a36813e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c @@ -0,0 +1,89 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -emit-llvm -triple arm64e -fbounds-safety %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s -o - | FileCheck %s + +#include +#include "mock-header.h" + + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[SIZ:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 10, ptr [[CNT]], align 4 +// CHECK-NEXT: store i32 4, ptr [[SIZ]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[CNT]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZ]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @my_calloc(i32 noundef [[TMP0]], i32 noundef [[TMP1]]) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[CALL]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[MUL]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP11]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[CNT]], align 4 +// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP12]], 1 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[SUB]] to i64 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[TMP13]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[TMP13]], [[WIDE_PTR_LB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT9:%.*]], label [[TRAP8:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP13]], align 4 +// CHECK-NEXT: ret i32 [[TMP16]] +// +int foo() { + int cnt = 10; + int siz = sizeof(int); + int *ptr = my_calloc(cnt, siz); + return ptr[cnt-1]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/mock-header.h b/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/mock-header.h new file mode 120000 index 0000000000000..25ba9d4bcc024 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/alloc-sized-calloc/mock-header.h @@ -0,0 +1 @@ +../../../BoundsSafety/CodeGen/alloc-sized-calloc/mock-header.h \ No newline at end of file diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/array-bound-deref-addrof.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/array-bound-deref-addrof.c new file mode 100644 index 0000000000000..2197b5247eb69 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/array-bound-deref-addrof.c @@ -0,0 +1,153 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +#include + +// CHECK-O0-LABEL: @foo( +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 +// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARR]], ptr [[TMP1]], align 8 +// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-O0: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARR]], ptr [[TMP3]], align 8 +// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 +// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP6]], align 8 +// CHECK-O0: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0: store ptr [[UPPER]], ptr [[TMP7]], align 8 +// CHECK-O0: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 +// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-O0: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 10 +// CHECK-O0: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-O0: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @foo( +// CHECK-O2: {{.*}}: +// CHECK-O2: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2: unreachable +// +int foo() { + int arr[10]; + int *ptr = *&arr; + return ptr[10]; +} + +// CHECK-O0-LABEL: @bar( +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 +// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARR]], ptr [[TMP1]], align 8 +// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-O0: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARR]], ptr [[TMP3]], align 8 +// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 +// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP6]], align 8 +// CHECK-O0: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0: store ptr [[UPPER]], ptr [[TMP7]], align 8 +// CHECK-O0: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 +// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-O0: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 9 +// CHECK-O0: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-O0: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @bar( +// CHECK-O2: {{.*}}: +// CHECK-O2: ret i32 undef +// +int bar() { + int arr[10]; + int *ptr = *&arr; + return ptr[9]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/array-decay.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/array-decay.c new file mode 100644 index 0000000000000..e397937981a0f --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/array-decay.c @@ -0,0 +1,101 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 + +// CHECK-O0-LABEL: @foo( +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 +// CHECK-O0: ret i32 [[TMP6]] +// +// CHECK-O2-LABEL: @foo( +// CHECK-O2: {{.*}}: +// CHECK-O2: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2: unreachable +// +int foo() { + int arr[10] = {0}; + int *ptr = arr; + return ptr[10]; +} + +// CHECK-O0-LABEL: @bar( +// CHECK-O0: {{.*}}: +// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: {{.*}}: +// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0: unreachable +// CHECK-O0: {{.*}}: +// CHECK-O0: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 +// CHECK-O0: ret i32 [[TMP6]] +// +// CHECK-O2-LABEL: @bar( +// CHECK-O2: entry: +// CHECK-O2: ret i32 0 +// +int bar() { + int arr[10] = {0}; + int *ptr = arr; + return ptr[9]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/const-bound-ptr-conversion.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/const-bound-ptr-conversion.c new file mode 100644 index 0000000000000..3e94635f98fc3 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/const-bound-ptr-conversion.c @@ -0,0 +1,56 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O0 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O2 +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O0 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O2 +// CHECK_O0-LABEL: @foo( +// CHECK_O0: {{.*}}: +// CHECK_O0: [[ARRAY:%.*]] = alloca [10 x i32], align 16 +// CHECK_O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK_O0: [[LOCAL:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK_O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK_O0: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 40, i1 false) +// CHECK_O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARRAY]], i64 0, i64 0 +// CHECK_O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK_O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK_O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK_O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK_O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK_O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK_O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK_O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LOCAL]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK_O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[LOCAL]], i64 24, i1 false) +// CHECK_O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK_O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK_O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK_O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK_O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK_O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK_O0: [[TMP3:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK_O0: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK_O0: trap: +// CHECK_O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK_O0: unreachable +// CHECK_O0: cont: +// CHECK_O0: [[TMP4:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK_O0: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK_O0: trap1: +// CHECK_O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK_O0: unreachable +// CHECK_O0: cont2: +// CHECK_O0: [[TMP5:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK_O0: ret i32 [[TMP5]] +// +// CHECK_O2-LABEL: @foo( +// CHECK_O2: {{.*}}: +// CHECK_O2: ret i32 0 +// +int foo(void) { + int array[10] = {0}; + int *ptr = array; + const int *local = ptr; + + return *local; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/constant-eval-count-static-init.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/constant-eval-count-static-init.c new file mode 100644 index 0000000000000..44ba3b6fde46f --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/constant-eval-count-static-init.c @@ -0,0 +1,59 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +#include + +typedef struct { + unsigned int *__sized_by(length) data; + int length; +} Item; + +static unsigned int _oidRsa[] = { 0, 1, 2 }; +const Item oidRsa = { _oidRsa, sizeof(_oidRsa)}; + +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca [[STRUCT_ITEM:%.*]], align 8 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 @oidRsa, i64 16, i1 false) +// CHECK-NEXT: [[LENGTH:%.*]] = getelementptr inbounds nuw [[STRUCT_ITEM]], ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LENGTH]], align 8 +// CHECK-NEXT: [[DATA:%.*]] = getelementptr inbounds nuw [[STRUCT_ITEM]], ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[DATA]], align 8 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 3 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[TMP5]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[TMP5]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont3: +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP5]], align 4 +// CHECK-NEXT: ret i32 [[TMP8]] +// +int main() { + return oidRsa.data[3]; // trap +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c new file mode 100644 index 0000000000000..551dc10a9760d --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 + + +// RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 + +#include + +struct S { + int *__counted_by(l) bp; + int *bp2 __counted_by(l+1); + int l; +}; + +// CHECK-O2-LABEL: define dso_local noundef i32 @foo +// CHECK-O2-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2:![0-9]+]] +// CHECK-O2-NEXT: unreachable, !annotation [[META2]] +// +int foo () { + int arr[10]; + struct S s = {arr, arr, 0}; + s.bp = &arr[1]; + s.l = 8; + s.bp2 = arr; + + return s.bp2[9]; // trap : oob s.bp2[9] +} + +// CHECK-O2-LABEL: define dso_local i32 @bar +// CHECK-O2-SAME: () local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 undef +// +int bar () { + int arr[10]; + struct S s = {arr, arr, 0}; + s.bp = &arr[1]; + s.l = 8; + s.bp2 = arr; + + return s.bp2[8]; // ok +} +//. +// CHECK-O2: [[META2]] = !{!"bounds-safety-generic", !"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c new file mode 100644 index 0000000000000..39a10e41bf936 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c @@ -0,0 +1,283 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 + +#include + +struct S { + int *__counted_by(l) bp; + int *bp2 __counted_by(l+1); + int l; +}; + +// CHECK-O0-LABEL: @foo( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O0-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP_TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP_TMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP43:%.*]] = alloca [[STRUCT_S]], align 8 +// CHECK-O0-NEXT: [[AGG_TEMP56:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP57:%.*]] = alloca [[STRUCT_S]], align 8 +// CHECK-O0-NEXT: [[AGG_TEMP73:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP74:%.*]] = alloca [[STRUCT_S]], align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER3:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY2]], i64 10 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER3]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: br i1 true, label [[CONT5:%.*]], label [[TRAP4:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap4: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont5: +// CHECK-O0-NEXT: [[BP:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 0 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[BP]], align 8 +// CHECK-O0-NEXT: [[BP2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 1 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[TMP_TMP1]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR8]], ptr [[BP2]], align 8 +// CHECK-O0-NEXT: [[L:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 2 +// CHECK-O0-NEXT: store i32 0, ptr [[L]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[S]], i64 20 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP6]], i8 0, i64 4, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY15:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER16:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY15]], i64 10 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY15]], ptr [[TMP7]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER16]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY15]], ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP11]], i64 1 +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP12]], align 8 +// CHECK-O0-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 +// CHECK-O0-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP14]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-O0-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY18:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER19:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY18]], i64 10 +// CHECK-O0-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY18]], ptr [[TMP19]], align 8 +// CHECK-O0-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER19]], ptr [[TMP20]], align 8 +// CHECK-O0-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY18]], ptr [[TMP21]], align 8 +// CHECK-O0-NEXT: br i1 true, label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap20: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont21: +// CHECK-O0-NEXT: br i1 true, label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap22: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont23: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[AGG_TEMP13]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8 +// CHECK-O0-NEXT: [[BP31:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR26]], ptr [[BP31]], align 8 +// CHECK-O0-NEXT: [[L32:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 2 +// CHECK-O0-NEXT: store i32 8, ptr [[L32]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8 +// CHECK-O0-NEXT: [[BP240:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR35]], ptr [[BP240]], align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-O0-NEXT: br label [[FOR_COND:%.*]] +// CHECK-O0: for.cond: +// CHECK-O0-NEXT: [[TMP22:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-O0-NEXT: [[L41:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[S]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP23:%.*]] = load i32, ptr [[L41]], align 8 +// CHECK-O0-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP22]], [[TMP23]] +// CHECK-O0-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-O0: for.body: +// CHECK-O0-NEXT: [[TMP24:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP43]], ptr align 8 [[S]], i64 24, i1 false) +// CHECK-O0-NEXT: [[L44:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP25:%.*]] = load i32, ptr [[L44]], align 8 +// CHECK-O0-NEXT: [[BP45:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP26:%.*]] = load ptr, ptr [[BP45]], align 8 +// CHECK-O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP25]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP26]], i64 [[IDX_EXT]] +// CHECK-O0-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP26]], ptr [[TMP27]], align 8 +// CHECK-O0-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP28]], align 8 +// CHECK-O0-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP26]], ptr [[TMP29]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 +// CHECK-O0-NEXT: [[TMP30:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-O0-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP30]] to i64 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR47]], i64 [[IDXPROM]] +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 +// CHECK-O0-NEXT: [[TMP31:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP31]], label [[CONT53:%.*]], label [[TRAP52:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap52: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont53: +// CHECK-O0-NEXT: [[TMP32:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP32]], label [[CONT55:%.*]], label [[TRAP54:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap54: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont55: +// CHECK-O0-NEXT: store i32 [[TMP24]], ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: br label [[FOR_INC:%.*]] +// CHECK-O0: for.inc: +// CHECK-O0-NEXT: [[TMP33:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-O0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP33]], 1 +// CHECK-O0-NEXT: store i32 [[INC]], ptr [[I]], align 4 +// CHECK-O0-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]] +// CHECK-O0: for.end: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[S]], i64 24, i1 false) +// CHECK-O0-NEXT: [[L58:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP34:%.*]] = load i32, ptr [[L58]], align 8 +// CHECK-O0-NEXT: [[BP259:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP35:%.*]] = load ptr, ptr [[BP259]], align 8 +// CHECK-O0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP34]], 1 +// CHECK-O0-NEXT: [[IDX_EXT60:%.*]] = sext i32 [[ADD]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR61:%.*]] = getelementptr inbounds i32, ptr [[TMP35]], i64 [[IDX_EXT60]] +// CHECK-O0-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP35]], ptr [[TMP36]], align 8 +// CHECK-O0-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR61]], ptr [[TMP37]], align 8 +// CHECK-O0-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP35]], ptr [[TMP38]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR63:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR62]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX64:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR63]], i64 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB66:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR65]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8 +// CHECK-O0-NEXT: [[TMP39:%.*]] = icmp ult ptr [[ARRAYIDX64]], [[WIDE_PTR_UB66]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP39]], label [[CONT70:%.*]], label [[TRAP69:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap69: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont70: +// CHECK-O0-NEXT: [[TMP40:%.*]] = icmp uge ptr [[ARRAYIDX64]], [[WIDE_PTR_LB68]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP40]], label [[CONT72:%.*]], label [[TRAP71:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap71: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont72: +// CHECK-O0-NEXT: [[TMP41:%.*]] = load i32, ptr [[ARRAYIDX64]], align 4 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP74]], ptr align 8 [[S]], i64 24, i1 false) +// CHECK-O0-NEXT: [[L75:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP74]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP42:%.*]] = load i32, ptr [[L75]], align 8 +// CHECK-O0-NEXT: [[BP76:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP74]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP43:%.*]] = load ptr, ptr [[BP76]], align 8 +// CHECK-O0-NEXT: [[IDX_EXT77:%.*]] = sext i32 [[TMP42]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR78:%.*]] = getelementptr inbounds i32, ptr [[TMP43]], i64 [[IDX_EXT77]] +// CHECK-O0-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP43]], ptr [[TMP44]], align 8 +// CHECK-O0-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR78]], ptr [[TMP45]], align 8 +// CHECK-O0-NEXT: [[TMP46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP43]], ptr [[TMP46]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR79:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR80:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR79]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX81:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR80]], i64 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB83:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR82]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB85:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR84]], align 8 +// CHECK-O0-NEXT: [[TMP47:%.*]] = icmp ult ptr [[ARRAYIDX81]], [[WIDE_PTR_UB83]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP47]], label [[CONT87:%.*]], label [[TRAP86:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap86: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont87: +// CHECK-O0-NEXT: [[TMP48:%.*]] = icmp uge ptr [[ARRAYIDX81]], [[WIDE_PTR_LB85]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP48]], label [[CONT89:%.*]], label [[TRAP88:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap88: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont89: +// CHECK-O0-NEXT: [[TMP49:%.*]] = load i32, ptr [[ARRAYIDX81]], align 4 +// CHECK-O0-NEXT: [[ADD90:%.*]] = add nsw i32 [[TMP41]], [[TMP49]] +// CHECK-O0-NEXT: ret i32 [[ADD90]] +// +// CHECK-O2-LABEL: @foo( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// +int foo () { + int arr[10]; + struct S s = {arr, arr, 0}; + s.bp = &arr[1]; + s.l = 8; + s.bp2 = arr; + // run-time check here + + for (int i = 0; i < s.l; ++i) + s.bp[i] = i; + + return s.bp2[8] + s.bp[8]; // trap : oob s.bp[8] +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c new file mode 100644 index 0000000000000..92f7309f51c0c --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c @@ -0,0 +1,130 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple x86_64 %s -o - | FileCheck %s +#include + +struct S { + int len; + int *__counted_by(len) ptr; +}; + +// CHECK-LABEL: @TestInitFail1( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void TestInitFail1() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {10, ptr}; // trap: +} + +// CHECK-LABEL: @TestInitFail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void TestInitFail2() { + int arr[9] = {0}; + int *ptr = arr; + int len = -1; + struct S s = {len, ptr}; // trap: +} + +struct SU { + unsigned long len; + int *__counted_by(len) ptr; +}; + +// CHECK-LABEL: @TestUInitFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void TestUInitFail() { + int arr[9] = {0}; + int *ptr = arr; + long len = -1; + struct SU s = {len, ptr}; // trap: +} + +// CHECK-LABEL: @TestUInitOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void TestUInitOK() { + int arr[9] = {0}; + int *ptr = arr; + long len = 8; + struct SU s = {len, ptr}; +} + +// CHECK-LABEL: @TestOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void TestOK() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {9, ptr}; +} + +// CHECK-LABEL: @TestAccessOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void TestAccessOK() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {9, ptr}; + (void)s.ptr[8]; +} + +// CHECK-LABEL: @TestAccessFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void TestAccessFail() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {9, ptr}; + (void)s.ptr[9]; +} + +// CHECK-LABEL: @TestAccessFail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [9 x i32], align 16 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 36, ptr nonnull [[ARR]]) #[[ATTR6:[0-9]+]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 36 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 -4 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT47:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont47: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 36, ptr nonnull [[ARR]]) #[[ATTR6]] +// CHECK-NEXT: ret void +// +void TestAccessFail2() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {9, ptr}; + (void)s.ptr[-1]; +} + +// CHECK-LABEL: @TestAccessFail3( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void TestAccessFail3() { + int arr[9] = {0}; + int *ptr = arr; + struct S s = {9, ptr}; + (void)*(s.ptr + 9); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/index-extension.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/index-extension.c new file mode 100644 index 0000000000000..01c1a5d818fcd --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-dependent-assignment-checks/index-extension.c @@ -0,0 +1,201 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK + +#include + +// CHECK-LABEL: @idx_char( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i8 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_char(int *__counted_by(n) dst, unsigned n, char idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_unsigned_char( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_unsigned_char(int *__counted_by(n) dst, unsigned n, unsigned char idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_short_int( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i16 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_short_int(int *__counted_by(n) dst, unsigned n, short int idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_short_unsigned( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = zext i16 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_short_unsigned(int *__counted_by(n) dst, unsigned n, short unsigned idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_int( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_int(int *__counted_by(n) dst, unsigned n, int idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_unsigned( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IDX:%.*]] to i64 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_unsigned(int *__counted_by(n) dst, unsigned n, unsigned idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_long_int( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_long_int(int *__counted_by(n) dst, unsigned n, long int idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_long_unsigned( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_long_unsigned(int *__counted_by(n) dst, unsigned n, long unsigned idx) { + // + dst[idx] = 0; +} + +// CHECK-LABEL: @idx_long_unsigned_counted_by_int( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[N:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont1: +// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void idx_long_unsigned_counted_by_int(int *__counted_by(n) dst, int n, long unsigned idx) { + // + dst[idx] = 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/count-return.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-return.c new file mode 100644 index 0000000000000..cc204b05da867 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/count-return.c @@ -0,0 +1,135 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +#include + +int *__sized_by(len) alloc(int len); + +// CHECK-O0-LABEL: @Test1( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[BUFAUTO:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[BUFBOUND:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 16, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[CALL:%.*]] = call ptr @alloc(i32 noundef [[TMP0]]) +// CHECK-O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[IDX_EXT]] +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[CALL]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[CALL]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[CALL1:%.*]] = call ptr @alloc(i32 noundef 40) +// CHECK-O0-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i8, ptr [[CALL1]], i64 40 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[CALL1]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR2]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[CALL1]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BUFBOUND]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ult ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp uge ptr [[TMP7]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP7]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP10]] +// +// CHECK-O2-LABEL: @Test1( +// CHECK-O2-NEXT: cont3: +// CHECK-O2-NEXT: [[CALL:%.*]] = tail call ptr @alloc(i32 noundef 16) #[[ATTR4:[0-9]+]] +// CHECK-O2-NEXT: [[CALL1:%.*]] = tail call ptr @alloc(i32 noundef 40) #[[ATTR4]] +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL1]], i64 36 +// CHECK-O2-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-O2-NEXT: ret i32 [[TMP1]] +// +int Test1() { + int len = 16; + int *bufAuto = alloc(len); + int *__bidi_indexable bufBound = alloc(sizeof(int) * 10); + return bufBound[9]; +} + +// CHECK-O0-LABEL: @Test2( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[BUFAUTO:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[BUFBOUND:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 16, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[CALL:%.*]] = call ptr @alloc(i32 noundef [[TMP0]]) +// CHECK-O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[IDX_EXT]] +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[CALL]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFAUTO]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[CALL]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[CALL1:%.*]] = call ptr @alloc(i32 noundef 40) +// CHECK-O0-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i8, ptr [[CALL1]], i64 40 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[CALL1]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR2]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BUFBOUND]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[CALL1]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BUFBOUND]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ult ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp uge ptr [[TMP7]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP7]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP10]] +// +// CHECK-O2-LABEL: @Test2( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[CALL:%.*]] = tail call ptr @alloc(i32 noundef 16) #[[ATTR4]] +// CHECK-O2-NEXT: [[CALL1:%.*]] = tail call ptr @alloc(i32 noundef 40) #[[ATTR4]] +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// +int Test2() { + int len = 16; + int *bufAuto = alloc(len); + int *__bidi_indexable bufBound = alloc(sizeof(int) * 10); + return bufBound[10]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O0.c new file mode 100644 index 0000000000000..db14a37c3e32e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O0.c @@ -0,0 +1,589 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 + + +// RUN: %clang_cc1 -fbounds-safety -Wno-bounds-safety-init-list -O0 -triple arm64 -emit-llvm %s -o - | FileCheck %s + +#include + +// TODO: rdar://114446928 +// CHECK-LABEL: define dso_local ptr @foo +// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// +int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { + return p; +} + +// CHECK-LABEL: define dso_local void @foo_assign +// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[SIZE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P2:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: store i32 [[TMP0]], ptr [[SIZE]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB3]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END39:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP8]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR10:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB12:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB14:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP15:%.*]] = icmp ule ptr [[WIDE_PTR_LB7]], [[WIDE_PTR_PTR10]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP15]], label [[LAND_RHS:%.*]], label [[LAND_END39]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP17]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR19]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB26]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR29]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP34]], label [[LAND_RHS36:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs36: +// CHECK-NEXT: [[CMP37:%.*]] = icmp sle i64 0, [[CONV]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP37]], [[LAND_RHS36]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP2]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END39]], !annotation [[META2]] +// CHECK: land.end39: +// CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP3]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR42]], ptr [[P2]], align 8 +// CHECK-NEXT: ret void +// +void foo_assign(int * __bidi_indexable p, int len) { + int size = len; + int * __counted_by_or_null(size) p2 = p; +} + +// CHECK-LABEL: define dso_local void @bar +// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: ret void +// +int * __bidi_indexable bar(int * __counted_by_or_null(len) p, int len) { + return p; +} + +// CHECK-LABEL: define dso_local void @bar_assign +// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: ret void +// +void bar_assign(int * __counted_by_or_null(len) p, int len) { + int * __bidi_indexable p2 = p; +} + +// CHECK-LABEL: define dso_local void @ptr_oob +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[Q:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP15:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP25:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[X]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[X]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[X]], ptr [[TMP3]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 -1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB3]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END34:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP14:%.*]] = icmp ule ptr [[WIDE_PTR_LB6]], [[WIDE_PTR_PTR9]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP14]], label [[LAND_RHS:%.*]], label [[LAND_END34]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP15]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR17:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB19:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB21:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR17]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP25]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR27:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR26]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB29:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR28]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB24]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR27]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP32:%.*]] = icmp sle i64 4, [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP32]], label [[LAND_RHS33:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs33: +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP13:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ true, [[LAND_RHS33]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP13]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END34]], !annotation [[META2]] +// CHECK: land.end34: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP14]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR37:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR36]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB39:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR38]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR37]], ptr [[Q]], align 8 +// CHECK-NEXT: ret void +// +void ptr_oob(void) { + int x; + int *__bidi_indexable p = &x; + --p; + int *__counted_by_or_null(4) q = p; +} + +// CHECK-LABEL: define dso_local void @null_count_neg +// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[Q:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP16:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP23:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P]], i8 0, i64 24, i1 false) +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META4]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB4]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END35:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP8]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR10:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB12:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB14:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP15:%.*]] = icmp ule ptr [[WIDE_PTR_LB7]], [[WIDE_PTR_PTR10]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP15]], label [[LAND_RHS:%.*]], label [[LAND_END35]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP16]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR18:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB20:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR19]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB22:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR18]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP23]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB25]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR28]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP33:%.*]] = icmp sle i64 -42, [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP33]], label [[LAND_RHS34:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs34: +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ false, [[LAND_RHS34]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP0]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END35]], !annotation [[META2]] +// CHECK: land.end35: +// CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP1]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: store i32 -42, ptr [[COUNT]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR38]], ptr [[Q]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[Q]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP4]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP11]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: ret void +// +int *__bidi_indexable null_count_neg(void) { + int *__bidi_indexable p = 0; + int count; + int *__counted_by_or_null(count) q; + count = -42; + q = p; + return q; +} + +// CHECK-LABEL: define dso_local void @null_count_too_big +// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[Q:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP16:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP23:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P]], i8 0, i64 24, i1 false) +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4]] +// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META4]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB4]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END35:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP8]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR10:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB12:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP8]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB14:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP15:%.*]] = icmp ule ptr [[WIDE_PTR_LB7]], [[WIDE_PTR_PTR10]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP15]], label [[LAND_RHS:%.*]], label [[LAND_END35]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP16]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR18:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB20:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR19]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB22:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR18]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP23]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB25]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR28]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP33:%.*]] = icmp sle i64 42, [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP33]], label [[LAND_RHS34:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs34: +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ true, [[LAND_RHS34]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP0]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END35]], !annotation [[META2]] +// CHECK: land.end35: +// CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP1]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: store i32 42, ptr [[COUNT]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR38]], ptr [[Q]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[Q]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP4]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_RESULT]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP11]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: ret void +// +int *__bidi_indexable null_count_too_big(void) { + int *__bidi_indexable p = 0; + int count; + int *__counted_by_or_null(count) q; + count = 42; + q = p; + return q; +} + +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O2.c new file mode 100644 index 0000000000000..f9825f548bac9 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted-by-or-null-from-bidi-O2.c @@ -0,0 +1,137 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + + +// RUN: %clang_cc1 -fbounds-safety -Wno-bounds-safety-init-list -O2 -triple arm64 -emit-llvm %s -o - | FileCheck %s + +#include + +// TODO: rdar://114446928 +// CHECK-LABEL: define dso_local ptr @foo( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: ret ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] +// +int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { + return p; +} + +// CHECK-LABEL: define dso_local void @foo_assign( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[LEN]] to i64 +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_2_0_P_SROA_IDX]], align 8 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_1_0_COPYLOAD]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label %[[TRAP:.*]], label %[[LAND_LHS_TRUE:.*]], !annotation [[META2]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 +// CHECK-NEXT: [[AGG_TEMP5_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_P_SROA_IDX]], align 8, !tbaa [[TBAA3:![0-9]+]] +// CHECK-NEXT: [[CMP15_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP5_SROA_1_0_COPYLOAD]], [[AGG_TEMP_SROA_0_0_COPYLOAD]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP15_NOT]], label %[[TRAP]], label %[[LAND_RHS:.*]], !annotation [[META2]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL_NOT]], label %[[CONT:.*]], label %[[LOR_RHS:.*]], !annotation [[META2]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_1_0_COPYLOAD]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2, !annotation [[META2]] +// CHECK-NEXT: [[CMP34:%.*]] = icmp sge i64 [[SUB_PTR_DIV]], [[CONV]], !annotation [[META2]] +// CHECK-NEXT: [[CMP37:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META2]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP37]], [[CMP34]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label %[[CONT]], label %[[TRAP]], !prof [[PROF10:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR7:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: ret void +// +void foo_assign(int * __bidi_indexable p, int len) { + int size = len; + int * __counted_by_or_null(size) p2 = p; +} + +// CHECK-LABEL: define dso_local void @bar( +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[P]], null, !annotation [[META11:![0-9]+]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[ADD_PTR_SINK:%.*]] = select i1 [[DOTNOT]], ptr null, ptr [[ADD_PTR]] +// CHECK-NEXT: store ptr [[P]], ptr [[AGG_RESULT]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_RESULT]], i64 8 +// CHECK-NEXT: store ptr [[ADD_PTR_SINK]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_RESULT]], i64 16 +// CHECK-NEXT: store ptr [[P]], ptr [[TMP1]], align 8 +// CHECK-NEXT: ret void +// +int * __bidi_indexable bar(int * __counted_by_or_null(len) p, int len) { + return p; +} + +// CHECK-LABEL: define dso_local void @bar_assign( +// CHECK-SAME: ptr noundef readnone captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret void +// +void bar_assign(int * __counted_by_or_null(len) p, int len) { + int * __bidi_indexable p2 = p; +} + +// CHECK-LABEL: define dso_local void @ptr_oob( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// CHECK-NEXT: [[TRAP:.*:]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR7]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// +void ptr_oob(void) { + int x; + int *__bidi_indexable p = &x; + --p; + int *__counted_by_or_null(4) q = p; +} + +// CHECK-LABEL: define dso_local void @null_count_neg( +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR3]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[AGG_RESULT]], i8 0, i64 24, i1 false) +// CHECK-NEXT: ret void +// +int *__bidi_indexable null_count_neg(void) { + int *__bidi_indexable p = 0; + int count; + int *__counted_by_or_null(count) q; + count = -42; + q = p; + return q; +} + +// CHECK-LABEL: define dso_local void @null_count_too_big( +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR3]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[AGG_RESULT]], i8 0, i64 24, i1 false) +// CHECK-NEXT: ret void +// +int *__bidi_indexable null_count_too_big(void) { + int *__bidi_indexable p = 0; + int count; + int *__counted_by_or_null(count) q; + count = 42; + q = p; + return q; +} + +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0} +// CHECK: [[META4]] = !{!"p1 int", [[META5:![0-9]+]], i64 0} +// CHECK: [[META5]] = !{!"any pointer", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"omnipotent char", [[META7:![0-9]+]], i64 0} +// CHECK: [[META7]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[META8]] = !{!"bounds-safety-generic", [[META9:![0-9]+]]} +// CHECK: [[META9]] = !{!"bounds-safety-missed-optimization-nsw", !"Check can not be removed because the arithmetic operation might wrap in the signed sense. Optimize the check by adding conditions to check for overflow before doing the operation"} +// CHECK: [[PROF10]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META11]] = !{!"bounds-safety-check-ptr-neq-null"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call-O2.c new file mode 100644 index 0000000000000..1c209d902b89e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call-O2.c @@ -0,0 +1,208 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s + +#include + +void foo(int *__counted_by_or_null(len) p, int len); + +// CHECK-LABEL: define dso_local void @caller_1( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @foo(ptr noundef null, i32 noundef 2) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: ret void +// +void caller_1() { + foo(0, 2); +} + +// CHECK-LABEL: define dso_local void @caller_2( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @foo(ptr noundef null, i32 noundef 0) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_2() { + foo(0, 0); +} + +// rdar://118117905 +// CHECK-LABEL: define dso_local void @caller_3( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[P]], null, !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[CMP_NOT65:%.*]] = icmp slt i32 [[LEN]], 0 +// CHECK-NEXT: [[CMP_NOT:%.*]] = and i1 [[DOTNOT]], [[CMP_NOT65]], !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6:[0-9]+]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_3(int *__counted_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_4( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK-LABEL: define dso_local void @caller_5( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR3]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK-LABEL: define dso_local void @caller_6( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[LEN]], 0, !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: land.rhs: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// +void caller_6(int *__counted_by(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_7( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_9_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_9_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_9_0_P_SROA_IDX]], align 8 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP_SROA_9_0_COPYLOAD]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_LHS_TRUE:%.*]], !annotation [[META3]] +// CHECK: land.lhs.true: +// CHECK-NEXT: [[AGG_TEMP_SROA_17_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 +// CHECK-NEXT: [[AGG_TEMP_SROA_17_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_17_0_P_SROA_IDX]], align 8, !tbaa [[TBAA4:![0-9]+]] +// CHECK-NEXT: [[CMP27_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_17_0_COPYLOAD]], [[AGG_TEMP_SROA_0_0_COPYLOAD]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27_NOT]], label [[TRAP]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: land.rhs: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[CONT:%.*]], label [[LOR_RHS:%.*]], !annotation [[META3]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[LEN]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_9_0_COPYLOAD]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META9:![0-9]+]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2, !annotation [[META3]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sge i64 [[SUB_PTR_DIV]], [[CONV]], !annotation [[META3]] +// CHECK-NEXT: [[CMP54:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP54]], [[CMP51]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT]], label [[TRAP]], !prof [[PROF11:![0-9]+]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[AGG_TEMP_SROA_0_0_COPYLOAD]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_8( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[P]], null, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = icmp ult i32 [[LEN]], 2 +// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL_NOT]], [[SPEC_SELECT]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF12:![0-9]+]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_8(int *__single p, int len) { + foo(p, len); +} + +void bar(int *__counted_by(*len) *out, int *len); + +// CHECK-LABEL: define dso_local void @caller_9( +// CHECK-SAME: ptr noundef [[OUT:%.*]], ptr noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @bar(ptr noundef [[OUT]], ptr noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_9(int *__counted_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK-LABEL: define dso_local ptr @caller_10( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META13:![0-9]+]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META13]] +// CHECK-NEXT: call void @bar(ptr noundef nonnull [[P]], ptr noundef nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA4]] +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[CMP_NOT83:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT83]], i1 false, !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META14:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META14]] +// CHECK: land.rhs: +// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT60:%.*]], !annotation [[META3]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CMP54:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] +// CHECK-NEXT: [[CMP57:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP57]], [[CMP54]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT60]], label [[TRAP]], !prof [[PROF11]], !annotation [[META3]] +// CHECK: cont60: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: ret ptr [[TMP0]] +// +int *__counted_by_or_null(len) caller_10(int len) { + int count; + int *__counted_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} + +//. +// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META3]] = !{!"bounds-safety-generic"} +// CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0} +// CHECK: [[META5]] = !{!"p1 int", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"any pointer", [[META7:![0-9]+]], i64 0} +// CHECK: [[META7]] = !{!"omnipotent char", [[META8:![0-9]+]], i64 0} +// CHECK: [[META8]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[META9]] = !{!"bounds-safety-generic", [[META10:![0-9]+]]} +// CHECK: [[META10]] = !{!"bounds-safety-missed-optimization-nsw", !"Check can not be removed because the arithmetic operation might wrap in the signed sense. Optimize the check by adding conditions to check for overflow before doing the operation"} +// CHECK: [[PROF11]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[PROF12]] = !{!"branch_weights", i32 2097151, i32 1} +// CHECK: [[META13]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META14]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call.c new file mode 100644 index 0000000000000..b6500d60d6a68 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_or_null_call.c @@ -0,0 +1,863 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s + +#include + +void foo(int *__counted_by_or_null(len) p, int len); + +// CHECK-LABEL: define dso_local void @caller_1( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2:![0-9]+]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 2) +// CHECK-NEXT: ret void +// +void caller_1() { + foo(0, 2); +} + +// CHECK-LABEL: define dso_local void @caller_2( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 0) +// CHECK-NEXT: ret void +// +void caller_2() { + foo(0, 0); +} + +// CHECK-LABEL: define dso_local void @caller_3( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs53: +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP13:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP13]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.end56: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP14]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR59:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR58]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB61:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR60]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB63:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR62]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR59]], i32 noundef [[TMP9]]) +// CHECK-NEXT: ret void +// +void caller_3(int *__counted_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_4( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[I]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 +// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR]], i32 noundef -1) +// CHECK-NEXT: ret void +// +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK-LABEL: define dso_local void @caller_5( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[I]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 +// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR]], i32 noundef 2) +// CHECK-NEXT: ret void +// +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK-LABEL: define dso_local void @caller_6( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs53: +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP9]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.end56: +// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP10]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR59:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR58]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB61:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR60]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB63:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR62]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR59]], i32 noundef [[TMP5]]) +// CHECK-NEXT: ret void +// +void caller_6(int *__counted_by(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_7( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs53: +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP4]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK: land.end56: +// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP5]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR59:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR58]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB61:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR60]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB63:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR62]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR59]], i32 noundef [[TMP0]]) +// CHECK-NEXT: ret void +// +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_8( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END29:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP13]], label [[LAND_RHS:%.*]], label [[LAND_END29]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[UPPER15:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER15]], ptr [[TMP11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB17]], ptr [[TMP13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR19]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP24:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP24]], label [[LAND_RHS26:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs26: +// CHECK-NEXT: [[CMP27:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP27]], [[LAND_RHS26]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP14]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END29]], !annotation [[META2]] +// CHECK: land.end29: +// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP15]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef [[TMP0]], i32 noundef [[TMP1]]) +// CHECK-NEXT: ret void +// +void caller_8(int *__single p, int len) { + foo(p, len); +} + +void bar(int *__counted_by(*len) *out, int *len); + +// CHECK-LABEL: define dso_local void @caller_9( +// CHECK-SAME: ptr noundef [[OUT:%.*]], ptr noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUT]], ptr [[OUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[LEN]], ptr [[LEN_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUT_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[LEN_ADDR]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP0]], ptr noundef [[TMP1]]) +// CHECK-NEXT: ret void +// +void caller_9(int *__counted_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK-LABEL: define dso_local ptr @caller_10( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP65:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP72:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META4]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr ptr, ptr [[P]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[P]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[P]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[COUNT]], i64 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[COUNT]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[COUNT]], ptr [[TMP7]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP8]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !annotation [[META6]] +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont4: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL12:%.*]], label [[CONT16:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull12: +// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_UB9]], !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !annotation [[META5]] +// CHECK: trap13: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont14: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT16]], label [[TRAP15:%.*]], !annotation [[META6]] +// CHECK: trap15: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont16: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR7]]) +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP14]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL18:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull18: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP15]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR21]], [[WIDE_PTR_UB28]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END62:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP39:%.*]] = icmp ule ptr [[WIDE_PTR_LB31]], [[WIDE_PTR_PTR34]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP39]], label [[LAND_RHS:%.*]], label [[LAND_END62]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR42]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP23]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP47]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB49]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR52]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP57:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP57]], label [[LAND_RHS59:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs59: +// CHECK-NEXT: [[CMP60:%.*]] = icmp sle i32 0, [[TMP23]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP24:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP60]], [[LAND_RHS59]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP25:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP24]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END62]], !annotation [[META2]] +// CHECK: land.end62: +// CHECK-NEXT: [[TMP26:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP25]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP26]], label [[CONT64:%.*]], label [[TRAP63:%.*]], !annotation [[META2]] +// CHECK: trap63: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont64: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP65]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR66:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR67:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR66]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR68:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB69:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR68]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB71:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR70]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR67]], ptr [[P]], align 8 +// CHECK-NEXT: store i32 [[TMP23]], ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP27:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP29:%.*]] = icmp ne ptr [[TMP27]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP29]], label [[BOUNDSCHECK_NOTNULL73:%.*]], label [[BOUNDSCHECK_NULL76:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull73: +// CHECK-NEXT: [[IDX_EXT74:%.*]] = sext i32 [[TMP28]] to i64 +// CHECK-NEXT: [[ADD_PTR75:%.*]] = getelementptr inbounds i32, ptr [[TMP27]], i64 [[IDX_EXT74]] +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR75]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP32]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT77:%.*]] +// CHECK: boundscheck.null76: +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP33]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP35]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT77]] +// CHECK: boundscheck.cont77: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR79:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR78]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB81:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR80]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB83:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR82]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR79]] +// +int *__counted_by_or_null(len) caller_10(int len) { + int count; + int *__counted_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META5]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_to_counted_by-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_to_counted_by-O2.c new file mode 100644 index 0000000000000..1e776843b365f --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/counted_by_to_counted_by-O2.c @@ -0,0 +1,134 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple x86_64 -emit-llvm %s -o - | FileCheck %s + +#include + +struct Packet { + int *__counted_by(len) buf; + int len; +}; + +struct PacketUnsigned { + int *__counted_by(len) buf; + unsigned long long len; +}; + +int *__counted_by(cnt) my_alloc_int(int cnt); +void *__sized_by(siz) my_alloc(int siz); +int *__sized_by(siz) my_alloc_int_siz(int siz); + + +// CHECK-LABEL: @TestCountIntFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef 9) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestCountIntFail(void) { + struct Packet p; + int siz = 9; + p.buf = my_alloc_int(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestCountNegFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestCountNegFail(void) { + struct Packet p; + int siz = -1; + p.buf = my_alloc_int(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestUCountNegFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestUCountNegFail(void) { + struct PacketUnsigned p; + int siz = -1; + p.buf = my_alloc_int(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestCountNegRetFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestCountNegRetFail(void) { + int *local_p = my_alloc_int(-1); //rdar://80808704 + (void)*local_p; +} + +// CHECK-LABEL: @TestCountIntOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef 10) #[[ATTR4]] +// CHECK-NEXT: ret void +// +void TestCountIntOK(void) { + struct Packet p; + int siz = 10; + p.buf = my_alloc_int(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestSizeFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc(i32 noundef 39) #[[ATTR4]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestSizeFail(void) { + struct Packet p; + int siz = 10 * sizeof(int) - 1; + p.buf = my_alloc(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestSizeOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc(i32 noundef 40) #[[ATTR4]] +// CHECK-NEXT: ret void +// +void TestSizeOK(void) { + struct Packet p; + int siz = 10 * sizeof(int); + p.buf = my_alloc(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestIntSizeFail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int_siz(i32 noundef 39) #[[ATTR4]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void TestIntSizeFail(void) { + struct Packet p; + int siz = 10 * sizeof(int) - 1; + p.buf = my_alloc_int_siz(siz); + p.len = 10; +} + +// CHECK-LABEL: @TestIntSizeOK( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int_siz(i32 noundef 40) #[[ATTR4]] +// CHECK-NEXT: ret void +// +void TestIntSizeOK(void) { + struct Packet p; + int siz = 10 * sizeof(int); + p.buf = my_alloc_int_siz(siz); + p.len = 10; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls-O2.c new file mode 100644 index 0000000000000..3fe7525c16289 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls-O2.c @@ -0,0 +1,63 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +// CHECK-LABEL: @f_inout_count( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void f_inout_count(int *__counted_by(*out_len) buf, int *out_len) {} + +// CHECK-LABEL: @success( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void success() { + int arr[10]; + int len = 10; + f_inout_count(arr, &len); +} + +// CHECK-LABEL: @fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation !{{[0-9]+}} +// CHECK-NEXT: unreachable +// +void fail() { + int arr[10]; + int len = 11; + f_inout_count(arr, &len); +} + +// CHECK-LABEL: @pass_out_len( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUT_LEN:%.*]], align 4, !tbaa [[TBAA3:![0-9]+]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[TMP0]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT:%.*]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation !{{[0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: ret void +// +void pass_out_len(int *__counted_by(*out_len) arr, int *out_len) { + f_inout_count(arr, out_len); +} + +// CHECK-LABEL: @pass_addr_of_len( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[LEN:%.*]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT77:%.*]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation !{{[0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont77: +// CHECK-NEXT: ret void +// +void pass_addr_of_len(int *__counted_by(len) arr, int len) { + f_inout_count(arr, &len); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls.c new file mode 100644 index 0000000000000..ba4b20f23c87a --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/dynamic-inout-count-calls.c @@ -0,0 +1,307 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @f_inout_count( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[OUT_LEN_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[BUF:%.*]], ptr [[BUF_ADDR]], align 8 +// CHECK-NEXT: store ptr [[OUT_LEN:%.*]], ptr [[OUT_LEN_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void f_inout_count(int *__counted_by(*out_len) buf, int *out_len) {} + +// CHECK-LABEL: @pass_addr_of_len( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP31:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP49:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP64:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP71:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[ARR:%.*]], ptr [[ARR_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARR_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[LEN_ADDR]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[LEN_ADDR]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[LEN_ADDR]], ptr [[TMP8]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP11]] to i64 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB14:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB14]], ptr [[TMP12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END61:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB24]], ptr [[TMP13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP31]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR33:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB35:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB37:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP38:%.*]] = icmp ule ptr [[WIDE_PTR_PTR26]], [[WIDE_PTR_PTR33]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP38]], label [[LAND_RHS:%.*]], label [[LAND_END61]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR44:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB46:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR45]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB48:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP49]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB55:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR54]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR44]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR51]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP56:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP56]], label [[LAND_RHS58:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.rhs58: +// CHECK-NEXT: [[CMP59:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_RHS]] ], [ [[CMP59]], [[LAND_RHS58]] ] +// CHECK-NEXT: br label [[LAND_END61]], {{!annotation ![0-9]+}} +// CHECK: land.end61: +// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[CONT4]] ], [ [[TMP15]], [[LAND_END]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT63:%.*]], label [[TRAP62:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap62: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont63: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP64]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR66:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR65]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB68:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR67]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB70:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR69]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = icmp ne ptr [[WIDE_PTR_PTR73]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT81:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP18:%.*]] = icmp ult ptr [[WIDE_PTR_PTR73]], [[WIDE_PTR_UB75]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT79:%.*]], label [[TRAP78:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap78: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont79: +// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR73]], [[WIDE_PTR_LB77]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT81]], label [[TRAP80:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap80: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont81: +// CHECK-NEXT: call void @f_inout_count(ptr noundef [[WIDE_PTR_PTR66]], ptr noundef [[WIDE_PTR_PTR73]]) +// CHECK-NEXT: ret void +// +void pass_addr_of_len(int *__counted_by(len) arr, int len) { + f_inout_count(arr, &len); +} + +// CHECK-LABEL: @pass_inout_len( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[OUT_LEN_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP30:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP39:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[ARR:%.*]], ptr [[ARR_ADDR]], align 8 +// CHECK-NEXT: store ptr [[OUT_LEN:%.*]], ptr [[OUT_LEN_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARR_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OUT_LEN_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[OUT_LEN_ADDR]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP7]] to i64 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END51:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB14:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB14]], ptr [[TMP9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP21]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR23:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP28:%.*]] = icmp ule ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_PTR23]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP28]], label [[LAND_RHS:%.*]], label [[LAND_END51]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP30]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB32]], ptr [[TMP10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP39]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR41:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB43:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR42]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB45:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR44]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR34]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR41]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP46:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP46]], label [[LAND_RHS48:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.rhs48: +// CHECK-NEXT: [[CMP49:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ false, [[LAND_RHS]] ], [ [[CMP49]], [[LAND_RHS48]] ] +// CHECK-NEXT: br label [[LAND_END51]], {{!annotation ![0-9]+}} +// CHECK: land.end51: +// CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP11]], [[LAND_END]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8 +// CHECK-NEXT: call void @f_inout_count(ptr noundef [[WIDE_PTR_PTR54]], ptr noundef [[TMP6]]) +// CHECK-NEXT: ret void +// +void pass_inout_len(int *__counted_by(*out_len) arr, int *out_len) { + f_inout_count(arr, out_len); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param-O2.c new file mode 100644 index 0000000000000..802d4e717a0b0 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param-O2.c @@ -0,0 +1,90 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +#include + +struct S { + int *end; + int *__ended_by(end) iter; +}; + +void foo(int * const __ended_by(end) start, int* const end); + + +// CHECK-LABEL: define dso_local void @good( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i32], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 160 +// CHECK-NEXT: call void @foo(ptr noundef nonnull [[ARR]], ptr noundef nonnull [[BOUND_PTR_ARITH]]) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void good(void) { + int arr[40]; + foo(arr, arr + 40); +} + +// CHECK-LABEL: define dso_local void @oob_upper( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i32], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 160 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 164 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[BOUND_PTR_ARITH]], [[UPPER]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[CMP28_NOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], !annotation [[META2]] +// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP28_NOT]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @foo(ptr noundef nonnull [[ARR]], ptr noundef [[BOUND_PTR_ARITH]]) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void oob_upper(void) { + int arr[40]; + foo(arr, arr + 41); +} + +// CHECK-LABEL: define dso_local void @oob_lower( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i32], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 160 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -4 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[BOUND_PTR_ARITH]], [[UPPER]], !annotation [[META2]] +// CHECK-NEXT: [[CMP28_NOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], !annotation [[META2]] +// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP28_NOT]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @foo(ptr noundef nonnull [[ARR]], ptr noundef [[BOUND_PTR_ARITH]]) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 160, ptr nonnull [[ARR]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void oob_lower(void) { + int arr[40]; + foo(arr, arr - 1); +} + +// CHECK-LABEL: define dso_local void @oob_order( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// +void oob_order(void) { + int arr[40]; + foo(arr + 2, arr + 1); +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048577, i32 1048575} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param.c new file mode 100644 index 0000000000000..b88fda158c69e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_const_param.c @@ -0,0 +1,118 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +#include + +struct S { + int *end; + int *__ended_by(end) iter; +}; + +// CHECK-LABEL: define dso_local void @foo( +// CHECK-SAME: ptr noundef [[START:%.*]], ptr noundef [[END:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[START_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[END_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LOCAL:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[START]], ptr [[START_ADDR]], align 8 +// CHECK-NEXT: store ptr [[END]], ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[START_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[LOCAL]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[LOCAL]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[LOCAL]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: ret void +// +void foo(int * const __ended_by(end) start, int* const end) { + int *local = end; +} + +// CHECK-LABEL: define dso_local void @bar( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i32], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [40 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 40 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [40 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER3:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY2]], i64 40 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP7]], i64 40 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR7]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR14:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB18:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR17]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR14]], ptr noundef [[WIDE_PTR_PTR21]]) +// CHECK-NEXT: ret void +// +void bar(void) { + int arr[40]; + foo(arr, arr + 40); +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr-O2.c new file mode 100644 index 0000000000000..21a8f07466f45 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr-O2.c @@ -0,0 +1,66 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +typedef void (*ended_by_t)(const char *__ended_by(end) start, const char *end); + +void ended_by(const char *__ended_by(end) start, const char *end); + +ended_by_t ended_by_p = &ended_by; + +struct { + char _dummy; + const char array[10]; + char _dummy2; +} x; + +// CHECK-LABEL: @ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @ended_by_p, align 8, {{!tbaa ![0-9]+}} +// CHECK-NEXT: tail call void [[TMP0]](ptr noundef nonnull getelementptr inbounds nuw (i8, ptr @x, i64 1), ptr noundef nonnull getelementptr inbounds nuw (i8, ptr @x, i64 11)) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: ret void +// +void ok(void) { + ended_by_p(x.array, x.array + 10); +} + +// FIXME: rdar://105524069 +// CHECK-LABEL: @start_fail_lower( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @ended_by_p, align 8, {{!tbaa ![0-9]+}} +// CHECK-NEXT: tail call void [[TMP0]](ptr noundef nonnull @x, ptr noundef nonnull getelementptr inbounds nuw (i8, ptr @x, i64 11)) #[[ATTR4]] +// CHECK-NEXT: ret void +// +void start_fail_lower(void) { + ended_by_p(x.array - 1, x.array + 10); +} + +// CHECK-LABEL: @start_fail_upper( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void start_fail_upper(void) { + ended_by_p(x.array + 11, x.array + 10); +} + +// CHECK-LABEL: @end_fail_lower( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void end_fail_lower(void) { + ended_by_p(x.array, x.array - 1); +} + +// CHECK-LABEL: @end_fail_upper( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void end_fail_upper(void) { + ended_by_p(x.array, x.array + 11); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr.c new file mode 100644 index 0000000000000..da2cc39c7e57a --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_func_ptr.c @@ -0,0 +1,94 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +typedef void (*ended_by_t)(const char *__ended_by(end) start, const char *end); + +void ended_by(const char *__ended_by(end) start, const char *end); + +ended_by_t ended_by_p = &ended_by; + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARRAY:%.*]] = alloca [10 x i8], align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], ptr [[ARRAY]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [10 x i8], ptr [[ARRAY]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER3:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY2]], i64 10 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP7]], i64 10 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr @ended_by_p, align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR14:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB18:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR17]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8 +// CHECK-NEXT: call void [[TMP15]](ptr noundef [[WIDE_PTR_PTR14]], ptr noundef [[WIDE_PTR_PTR21]]) +// CHECK-NEXT: ret void +// +void foo(void) { + const char array[10]; + ended_by_p(array, array + 10); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_returns.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_returns.c new file mode 100644 index 0000000000000..4cbd26dad176a --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ended_by_returns.c @@ -0,0 +1,364 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// TODO: rdar://83900556 +// CHECK-LABEL: @chunk( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BEGIN_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[END_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[BEGIN:%.*]], ptr [[BEGIN_ADDR]], align 8 +// CHECK-NEXT: store ptr [[END:%.*]], ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BEGIN_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[BEGIN_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP7]], i64 1 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// +char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { + return begin + 1; +} + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[ARRAYDECAY5:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER6:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY5]], i64 10 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY5]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP10]], i64 10 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR8]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB10]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB12]], ptr [[TMP20]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 +// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_PTR38]] +// CHECK-NEXT: br label [[LAND_END]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP22:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP43]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR46]], ptr noundef [[WIDE_PTR_PTR53]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP58]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR62:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR61]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB64:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR63]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB66:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR65]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB64]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: ret void +// +void foo(void) { + int arr[10]; + int *p = chunk(arr, arr+10); +} + +// CHECK-LABEL: @fooCast( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[ARRAYDECAY5:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER6:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY5]], i64 10 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY5]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP10]], i64 10 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP4]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR8]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB10]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB12]], ptr [[TMP20]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 +// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_PTR38]] +// CHECK-NEXT: br label [[LAND_END]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP22:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP43]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR46]], ptr noundef [[WIDE_PTR_PTR53]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP58]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR62:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR61]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB64:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR63]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB66:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR65]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB64]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: ret void +// +void fooCast(void) { + int arr[10]; + int *p = (int*)chunk(arr, arr+10); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-assignment.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-assignment.c new file mode 100644 index 0000000000000..168085fa8b9c0 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-assignment.c @@ -0,0 +1,121 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int count; + int elems[__counted_by(count)]; +} flex_t; + +// CHECK-LABEL: @test( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[FLEX_BIDI_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: store ptr [[FLEX_BIDI:%.*]], ptr [[FLEX_BIDI_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[FLEX_BIDI]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT21:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FLEX_T:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont11: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont13: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: br i1 true, label [[CONT15:%.*]], label [[TRAP14:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap14: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont15: +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT17:%.*]], label [[TRAP16:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap16: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont17: +// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT19:%.*]], label [[TRAP18:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap18: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont19: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 123, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT21]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap20: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont21: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR23:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR23]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT31:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR23]], [[WIDE_PTR_UB25]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT29:%.*]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap28: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont29: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR23]], [[WIDE_PTR_LB27]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT31]], label [[TRAP30:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap30: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont31: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR23]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP10]], i32 0, i32 0 +// CHECK-NEXT: store i32 123, ptr [[COUNT]], align 4 +// CHECK-NEXT: ret void +// +void test(flex_t *flex, flex_t *__bidi_indexable flex_bidi) { + flex = flex_bidi; + flex->count = 123; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-checks-no-count-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-checks-no-count-O2.c new file mode 100644 index 0000000000000..4d4a35afafa57 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-checks-no-count-O2.c @@ -0,0 +1,297 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int count; + int elems[]; +} flex_t; + +// CHECK-LABEL: @test_under_base_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [20 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7:[0-9]+]] +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -1 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[BOUND_PTR_ARITH]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[CONT8:%.*]], label [[BOUNDSCHECK_NOTNULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 20 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT8]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont8: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: ret void +// +void test_under_base_fail() { + char arr[20]; + char *oob_ptr = arr - 1; + flex_t *__single flex = (flex_t *)oob_ptr; +} + +// CHECK-LABEL: @test_under_base_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_under_base_ok() { + char arr[20]; + char *oob_ptr = arr - 1; + flex_t *flex = (flex_t *)oob_ptr; +} + + +// CHECK-LABEL: @test_under_base_fail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [20 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -1 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont8: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: ret void +// +void test_under_base_fail2() { + char arr[20]; + char *oob_ptr = arr - 1; + flex_t *flex = (flex_t *)oob_ptr; + int a = flex->count; +} + + +// CHECK-LABEL: @test_over_base_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void test_over_base_fail() { + char arr[20]; + char *oob_ptr = arr + 20; + flex_t *__single flex = (flex_t *)oob_ptr; +} + +// CHECK-LABEL: @test_over_base_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_over_base_ok() { + char arr[20]; + char *oob_ptr = arr + 20; + flex_t *flex = (flex_t *)oob_ptr; +} + +// CHECK-LABEL: @test_over_base_fail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [20 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 20 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 24 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont8: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: ret void +// +void test_over_base_fail2() { + char arr[20]; + char *oob_ptr = arr + 20; + flex_t *flex = (flex_t *)oob_ptr; + int a = flex->count; +} + +// FIXME: rdar://84809738 +// CHECK-LABEL: @test_small_base_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_small_base_fail(flex_t *flex) { + char arr[3]; + flex = (flex_t *)arr; +} + +// CHECK-LABEL: @test_small_base_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_small_base_ok() { + char arr[3]; + flex_t *flex = (flex_t *)arr; +} + +// CHECK-LABEL: @test_small_base_fail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_small_base_fail2() { + char arr[3]; + flex_t *flex = (flex_t *)arr; + (void)(*flex); +} + +// CHECK-LABEL: @test_base_only_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_base_only_ok() { + char arr[20]; + flex_t *__single flex = (flex_t *)arr; +} + +// CHECK-LABEL: @test_count_from_buf_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_count_from_buf_ok() { + char arr[4]; + flex_t *__single flex = (flex_t *)arr; +} + +// CHECK-LABEL: @test_count_from_buf_ok2( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_count_from_buf_ok2(flex_t *flex) { + char arr[4]; + flex = (flex_t *)arr; +} + +// FIXME: rdar://84809738 +// CHECK-LABEL: @test_count_from_buf_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_count_from_buf_fail() { + char arr[3]; + flex_t *__single flex = (flex_t *)arr; +} + +// CHECK-LABEL: @test_base_count_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_base_count_ok(flex_t *__single flex) { + char arr[20]; + flex = (flex_t *)arr; + (void)flex->count; +} + +// CHECK-LABEL: @test_base_fam_access_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void test_base_fam_access_fail(flex_t *__single flex) { + char arr[20]; + flex = (flex_t *)arr; + flex->elems[0] = 0; +} + +// CHECK-LABEL: @test_base_fam_access_fail2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void test_base_fam_access_fail2(flex_t *__single flex) { + char arr[20]; + flex = (flex_t *)arr; + flex->elems[1] = 0; +} + +// FIXME: rdar://80820825 +// CHECK-LABEL: @test_null_base_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: unreachable +// +void test_null_base_fail(flex_t *__single flex) { + flex = 0; + flex->count = 4; +} + +// CHECK-LABEL: @test_null_base_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_null_base_ok(flex_t *__single flex) { + flex = 0; +} + +// CHECK-LABEL: @test_null_base_fam_access_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void test_null_base_fam_access_fail(flex_t *__single flex) { + flex = 0; + + flex->elems[4] = 42; +} + +typedef struct { + unsigned dummy; + flex_t *flex; +} flex_wrapper_t; + +// CHECK-LABEL: @test_flex_init_list_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_flex_init_list_ok() { + char buf[4]; + flex_t *flex = (flex_t *)buf; + flex_wrapper_t flex_wrap = {0, flex}; +} + +// FIXME: rdar://84809738 +// CHECK-LABEL: @test_flex_init_list_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void test_flex_init_list_fail() { + char buf[3]; + flex_t *flex = (flex_t *)buf; + flex_wrapper_t flex_wrap = {0, flex}; +} + +void sink(flex_t *__single flex); + +// CHECK-LABEL: @test_flex_argument_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca [4 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: call void @sink(ptr noundef nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: ret void +// +void test_flex_argument_ok() { + char buf[4]; + flex_t *flex = (flex_t *)buf; + sink(flex); +} + +// FIXME: rdar://84809738 +// CHECK-LABEL: @test_flex_argument_fail( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: call void @sink(ptr noundef nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: ret void +// +void test_flex_argument_fail() { + char buf[3]; + flex_t *flex = (flex_t *)buf; + sink(flex); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-const-call.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-const-call.c new file mode 100644 index 0000000000000..db1a3befb30d7 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-const-call.c @@ -0,0 +1,143 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +unsigned data_const_global_count __unsafe_late_const; + +// CHECK-LABEL: @get_const_count( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @data_const_global_count, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +__attribute__((const)) int get_const_count() { + return data_const_global_count; +} + +struct struct_flex { + void *dummy; + int fam[__counted_by(get_const_count())]; +}; + +// CHECK-LABEL: @test( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[NEW_PTR:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP2]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT28:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr [[STRUCT_STRUCT_FLEX:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB14:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr [[STRUCT_STRUCT_FLEX]], ptr [[WIDE_PTR_PTR12]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB14]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT18:%.*]], label [[TRAP17:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap17: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont18: +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT20:%.*]], label [[TRAP19:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap19: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont20: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCT_FLEX]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: [[CALL:%.*]] = call i32 @get_const_count() #[[ATTR5:[0-9]+]] +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[CALL]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap21: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont22: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap23: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont24: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap25: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont26: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[CALL]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT28]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap27: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont28: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT38:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_UB32]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT36:%.*]], label [[TRAP35:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap35: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont36: +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT38]], label [[TRAP37:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap37: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont38: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR30]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void test(struct struct_flex *flex, void *__bidi_indexable new_ptr) { + flex = new_ptr; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-multiple-decls.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-multiple-decls.c new file mode 100644 index 0000000000000..5c6b2ad286a91 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-multiple-decls.c @@ -0,0 +1,202 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int len; + int offs; + int fam[__counted_by(len - offs)]; +} S; + + +// CHECK-LABEL: @trap_len_too_big( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i8], align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[S:%.*]], ptr [[S_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [40 x i8], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY]], i64 40 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT29:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_S:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP6]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB14:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr [[STRUCT_S]], ptr [[WIDE_PTR_PTR12]], i64 1 +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[TMP8]], [[WIDE_PTR_UB14]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT18:%.*]], label [[TRAP17:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap17: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont18: +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT20:%.*]], label [[TRAP19:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap19: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont20: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY21:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: br i1 true, label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap22: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont23: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[ARRAYDECAY21]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT25:%.*]], label [[TRAP24:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap24: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont25: +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT27:%.*]], label [[TRAP26:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap26: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont27: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY21]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 9, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT29]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap28: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont29: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR31]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT39:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_UB33]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT37:%.*]], label [[TRAP36:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap36: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont37: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_LB35]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT39]], label [[TRAP38:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap38: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont39: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR31]], ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[OFFS:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP16]], i32 0, i32 1 +// CHECK-NEXT: store i32 2, ptr [[OFFS]], align 4 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP17]], i32 0, i32 0 +// CHECK-NEXT: store i32 11, ptr [[LEN]], align 4 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[FAM41:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY42:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM41]], i64 0, i64 0 +// CHECK-NEXT: [[FAM44:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY45:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM44]], i64 0, i64 0 +// CHECK-NEXT: [[LEN46:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 0 +// CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[LEN46]], align 4 +// CHECK-NEXT: [[OFFS47:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 1 +// CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[OFFS47]], align 4 +// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP19]], [[TMP20]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[SUB]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY45]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB49]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY42]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR51]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY42]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR53]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = icmp ult ptr [[TMP28]], [[WIDE_PTR_UB55]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP29]], label [[CONT59:%.*]], label [[TRAP58:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap58: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont59: +// CHECK-NEXT: [[TMP30:%.*]] = icmp uge ptr [[TMP28]], [[WIDE_PTR_LB57]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP30]], label [[CONT61:%.*]], label [[TRAP60:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap60: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont61: +// CHECK-NEXT: store i32 0, ptr [[TMP28]], align 4 +// CHECK-NEXT: ret void +// +void trap_len_too_big(S *s) { + char arr[40] = {0}; + s = (S *)arr; + s->offs = 2; + s->len = 11; + + s->fam[0] = 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-assignment.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-assignment.c new file mode 100644 index 0000000000000..b8bfbe3a14091 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-assignment.c @@ -0,0 +1,398 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int count; + int elems[__counted_by(count)]; +} flex_t; + +// CHECK-LABEL: @pointer_assign( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: ret void +// +void pointer_assign(flex_t *flex) { + flex_t *b = flex; +} + +// CHECK-LABEL: @pointer_assign_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[S:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP16:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT35:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont11: +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont13: +// CHECK-NEXT: [[ELEMS14:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY15:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS14]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP16]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR18:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB20:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR19]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP16]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB22:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR21]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR18]], i64 1 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB20]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap23: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont24: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_LB22]], [[WIDE_PTR_PTR18]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap25: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont26: +// CHECK-NEXT: [[COUNT27:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR18]], i32 0, i32 0 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[COUNT27]], align 4 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP17]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT29:%.*]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap28: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont29: +// CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[ARRAYDECAY15]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT31:%.*]], label [[TRAP30:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap30: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont31: +// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT33:%.*]], label [[TRAP32:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap32: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont33: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY15]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP17]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT35]], label [[TRAP34:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap34: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont35: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR37:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR36]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB39:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR38]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = icmp ne ptr [[WIDE_PTR_PTR37]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP20]], label [[BOUNDSCHECK_NOTNULL42:%.*]], label [[CONT46:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull42: +// CHECK-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR37]], [[WIDE_PTR_UB39]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP21]], label [[CONT44:%.*]], label [[TRAP43:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap43: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont44: +// CHECK-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR37]], [[WIDE_PTR_LB41]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP22]], label [[CONT46]], label [[TRAP45:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap45: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont46: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR37]], ptr [[S]], align 8 +// CHECK-NEXT: ret void +// +void pointer_assign_single(flex_t *flex) { + flex_t *__single s = flex; +} + +// CHECK-LABEL: @pointer_and_count_assign( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[B]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[B]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: [[COUNT3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: store i32 10, ptr [[COUNT3]], align 4 +// CHECK-NEXT: ret void +// +void pointer_and_count_assign(flex_t *flex) { + flex_t *b = flex; + b->count = 10; +} + +// CHECK-LABEL: @pointer_and_count_assign_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT23:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont11: +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont13: +// CHECK-NEXT: [[ELEMS14:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY15:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS14]], i64 0, i64 0 +// CHECK-NEXT: br i1 true, label [[CONT17:%.*]], label [[TRAP16:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap16: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont17: +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[ARRAYDECAY15]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT19:%.*]], label [[TRAP18:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap18: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont19: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap20: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont21: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY15]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 10, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT23]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap22: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont23: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR25:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB27:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR26]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB29:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR28]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[WIDE_PTR_PTR25]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL30:%.*]], label [[CONT34:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull30: +// CHECK-NEXT: [[TMP17:%.*]] = icmp ult ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_UB27]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT32:%.*]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap31: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont32: +// CHECK-NEXT: [[TMP18:%.*]] = icmp uge ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_LB29]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT34]], label [[TRAP33:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap33: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont34: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR25]], ptr [[B]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[COUNT35:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP19]], i32 0, i32 0 +// CHECK-NEXT: store i32 10, ptr [[COUNT35]], align 4 +// CHECK-NEXT: ret void +// +void pointer_and_count_assign_single(flex_t *flex) { + flex_t *__single b = flex; + b->count = 10; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-deref.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-deref.c new file mode 100644 index 0000000000000..8720b9ada9973 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-deref.c @@ -0,0 +1,459 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int count; + int elems[__counted_by(count)]; +} flex_t; + +flex_t g_flex = {2, {1, 2}}; + +// CHECK-LABEL: @addrof_g( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @g_flex, align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds nuw ([[STRUCT_FLEX_T:%.*]], ptr @g_flex, i32 0, i32 1), i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr @g_flex, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr @g_flex, ptr [[TMP3]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT32:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont11: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont13: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap21: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont22: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_LB20]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap23: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont24: +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap25: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont26: +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT28:%.*]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap27: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont28: +// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT30:%.*]], label [[TRAP29:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap29: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont30: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP12]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap31: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont32: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[WIDE_PTR_PTR34]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT42:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ult ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT40:%.*]], label [[TRAP39:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap39: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont40: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT42]], label [[TRAP41:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap41: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont42: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR34]] +// +flex_t *addrof_g(void) { + return &g_flex; +} + +// CHECK-LABEL: @addrof_deref_g( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca [[STRUCT_FLEX_T:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @g_flex, align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds nuw ([[STRUCT_FLEX_T]], ptr @g_flex, i32 0, i32 1), i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr @g_flex, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr @g_flex, ptr [[TMP3]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont4: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[AGG_TEMP1]], ptr align 4 [[WIDE_PTR_PTR]], i64 4, i1 false) +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: [[ELEMS6:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY7:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS6]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT8:%.*]] = sext i32 [[TMP6]] to i64 +// CHECK-NEXT: [[ADD_PTR9:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY7]], i64 [[IDX_EXT8]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[AGG_TEMP1]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR9]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[AGG_TEMP1]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB11]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR15]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ult ptr [[TMP14]], [[WIDE_PTR_UB17]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap20: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont21: +// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[TMP14]], [[WIDE_PTR_LB19]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap22: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont23: +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP14]], align 4 +// CHECK-NEXT: ret i32 [[TMP17]] +// +int addrof_deref_g(void) { + return (*&g_flex).elems[0]; +} + +// CHECK-LABEL: @assigning_array_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[FLEX:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca [[STRUCT_FLEX_T:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP62:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P:%.*]], ptr [[P_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT32:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont11: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont13: +// CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap21: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont22: +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_LB20]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap23: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont24: +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i32 0, i32 0 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap25: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont26: +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT28:%.*]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap27: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont28: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT30:%.*]], label [[TRAP29:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap29: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont30: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP8]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap31: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont32: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR34]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT42:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT40:%.*]], label [[TRAP39:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap39: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont40: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT42]], label [[TRAP41:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap41: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont42: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR34]], ptr [[FLEX]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[FLEX]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP14]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL46:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull46: +// CHECK-NEXT: [[ELEMS47:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP14]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY48:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS47]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT49:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP14]], i32 0, i32 0 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[COUNT49]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP16]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY48]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB55:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR54]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ult ptr [[WIDE_PTR_PTR51]], [[WIDE_PTR_UB53]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP23]], label [[CONT57:%.*]], label [[TRAP56:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap56: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont57: +// CHECK-NEXT: [[TMP24:%.*]] = icmp uge ptr [[WIDE_PTR_PTR51]], [[WIDE_PTR_LB55]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP24]], label [[CONT59:%.*]], label [[TRAP58:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap58: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont59: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[AGG_TEMP44]], ptr align 4 [[WIDE_PTR_PTR51]], i64 4, i1 false) +// CHECK-NEXT: [[ELEMS60:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY61:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS60]], i64 0, i64 0 +// CHECK-NEXT: [[ELEMS63:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY64:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS63]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT65:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 0 +// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[COUNT65]], align 4 +// CHECK-NEXT: [[IDX_EXT66:%.*]] = sext i32 [[TMP25]] to i64 +// CHECK-NEXT: [[ADD_PTR67:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY64]], i64 [[IDX_EXT66]] +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[AGG_TEMP44]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR67]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[AGG_TEMP44]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR68:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB69:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR68]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB69]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR71:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR70]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY61]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR71]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY61]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR73]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = icmp ult ptr [[TMP33]], [[WIDE_PTR_UB75]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP34]], label [[CONT79:%.*]], label [[TRAP78:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap78: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont79: +// CHECK-NEXT: [[TMP35:%.*]] = icmp uge ptr [[TMP33]], [[WIDE_PTR_LB77]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP35]], label [[CONT81:%.*]], label [[TRAP80:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap80: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont81: +// CHECK-NEXT: store i32 10, ptr [[TMP33]], align 4 +// CHECK-NEXT: ret void +// +void assigning_array_single(flex_t *__bidi_indexable p) { + flex_t *__single flex = p; + (*flex).elems[0] = 10; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-returns-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-returns-O2.c new file mode 100644 index 0000000000000..eaa2ca8388bbe --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-promotion-returns-O2.c @@ -0,0 +1,120 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + + +#include + +typedef struct { + int count; + int elems[__counted_by(count)]; +} flex_t; + +inline flex_t *return_flex(int *__counted_by(11) buf) { + return (flex_t *)buf; +} + +// CHECK-LABEL: @pointer_assign_good( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_assign_good() { + int arr[11] = {10}; + flex_t *__single a; + a = return_flex(arr); +} + +// CHECK-LABEL: @pointer_assign_good2( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_assign_good2() { + int arr[11] = {10}; + flex_t *__single a; + a = (flex_t *)return_flex(arr); +} + +// CHECK-LABEL: @pointer_init_good( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_init_good() { + int arr[11] = {10}; + flex_t *__single a = return_flex(arr); +} + +// CHECK-LABEL: @pointer_init_good2( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_init_good2() { + int arr[11] = {10}; + flex_t *__single a = (flex_t *)return_flex(arr); +} + +// CHECK-LABEL: @pointer_count_assign_trap( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void pointer_count_assign_trap() { + int arr[11] = {10}; + flex_t *__single a; + a = return_flex(arr); + a->count = 11; +} + +// CHECK-LABEL: @pointer_count_init_trap( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void pointer_count_init_trap() { + int arr[11] = {10}; + flex_t *__single a = return_flex(arr); + a->count = 11; +} + +// CHECK-LABEL: @pointer_count_assign_good( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_count_assign_good() { + int arr[11] = {10}; + flex_t *__single a; + a = return_flex(arr); + a->count = 9; +} + +// CHECK-LABEL: @pointer_count_init_good( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void pointer_count_init_good() { + int arr[11] = {10}; + flex_t *__single a = return_flex(arr); + a->count = 9; +} + +// CHECK-LABEL: @elem_access_good( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void +// +void elem_access_good() { + int arr[11] = {10}; + flex_t *__single a; + a = return_flex(arr); + a->elems[9] = 0; +} + +// CHECK-LABEL: @elem_access_trap( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// +void elem_access_trap() { + int arr[11] = {10}; + flex_t *__single a; + a = return_flex(arr); + a->elems[10] = 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O0.c new file mode 100644 index 0000000000000..ce6b0ddd7d76d --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O0.c @@ -0,0 +1,562 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +#include + +struct Inner { + int * __counted_by(len) ptr; + int len; +}; +struct Outer { + struct Inner hdr; + int fam[__counted_by(hdr.len)]; +}; + +struct Outer * __sized_by(sizeof(struct Outer) + sizeof(int) * len) bar(int len); +int * __counted_by(len) baz(int len); + +// CHECK-LABEL: define dso_local ptr @foo( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*]]: +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP80:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @baz(i32 noundef [[TMP0]]) +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[CALL1:%.*]] = call ptr @bar(i32 noundef [[TMP4]]) +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 +// CHECK-NEXT: [[MUL:%.*]] = mul i64 4, [[CONV]] +// CHECK-NEXT: [[ADD:%.*]] = add i64 16, [[MUL]] +// CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[ADD]], 0 +// CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 [[ADD]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR3]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL1]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[P2]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB8]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP9]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END39:.*]], !annotation [[META2]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP21:%.*]] = icmp ule ptr [[WIDE_PTR_LB13]], [[WIDE_PTR_PTR16]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP21]], label %[[LAND_RHS:.*]], label %[[LAND_END39]], !annotation [[META2]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: [[CONV23:%.*]] = sext i32 [[TMP8]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB26]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR29]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i64 [[CONV23]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP34]], label %[[LAND_RHS36:.*]], label %[[LAND_END:.*]], !annotation [[META2]] +// CHECK: [[LAND_RHS36]]: +// CHECK-NEXT: [[CMP37:%.*]] = icmp sle i32 0, [[TMP8]], !annotation [[META2]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META2]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, %[[LAND_RHS]] ], [ [[CMP37]], %[[LAND_RHS36]] ] +// CHECK-NEXT: br label %[[LAND_END39]], !annotation [[META2]] +// CHECK: [[LAND_END39]]: +// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[TMP9]], %[[LAND_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP41]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR43:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR42]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB45:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR44]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB47:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR46]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR43]], null, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label %[[FLEX_BASE_NONNULL:.*]], label %[[CONT68:.*]], !annotation [[META4]] +// CHECK: [[FLEX_BASE_NONNULL]]: +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_OUTER:%.*]], ptr [[WIDE_PTR_PTR43]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[WIDE_PTR_PTR43]], [[TMP11]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT49:.*]], label %[[TRAP48:.*]], !prof [[PROF3]], !annotation [[META5]] +// CHECK: [[TRAP48]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: [[CONT49]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR52]], i64 1 +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB54]], !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT58:.*]], label %[[TRAP57:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP57]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT58]]: +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_LB56]], [[WIDE_PTR_PTR52]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT60:.*]], label %[[TRAP59:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP59]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT60]]: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR52]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP8]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label %[[CONT62:.*]], label %[[TRAP61:.*]], !prof [[PROF3]], !annotation [[META8]] +// CHECK: [[TRAP61]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META8]] +// CHECK-NEXT: unreachable, !annotation [[META8]] +// CHECK: [[CONT62]]: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB45]], !annotation [[META9:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP16]], label %[[CONT64:.*]], label %[[TRAP63:.*]], !prof [[PROF3]], !annotation [[META9]] +// CHECK: [[TRAP63]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: [[CONT64]]: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR43]], [[WIDE_PTR_LB47]], !annotation [[META10:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP17]], label %[[CONT66:.*]], label %[[TRAP65:.*]], !prof [[PROF3]], !annotation [[META10]] +// CHECK: [[TRAP65]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META10]] +// CHECK-NEXT: unreachable, !annotation [[META10]] +// CHECK: [[CONT66]]: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB45]] to i64, !annotation [[META11:![0-9]+]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META11]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP8]] to i64, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label %[[CONT68]], label %[[TRAP67:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP67]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT68]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR70:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR69]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB72:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR71]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = icmp ne ptr [[WIDE_PTR_PTR70]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT78:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP19:%.*]] = icmp ult ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_UB72]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP19]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP75]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT76]]: +// CHECK-NEXT: [[TMP20:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT78]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP77]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT78]]: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[P]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP21]], i32 0, i32 0 +// CHECK-NEXT: [[LEN79:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN79]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP80]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR81:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR82:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR81]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB84:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR83]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB86:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR85]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR87:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP22]], i32 0, i32 0 +// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR87]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR82]], ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[TMP23]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP24]], label %[[BOUNDSCHECK_NOTNULL89:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL89]]: +// CHECK-NEXT: [[FAM90:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY91:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM90]], i64 0, i64 0 +// CHECK-NEXT: [[HDR92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 +// CHECK-NEXT: [[LEN93:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR92]], i32 0, i32 1 +// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[LEN93]], align 8 +// CHECK-NEXT: [[IDX_EXT94:%.*]] = sext i32 [[TMP25]] to i64 +// CHECK-NEXT: [[ADD_PTR95:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY91]], i64 [[IDX_EXT94]] +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR95]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP28]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP31]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR96:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR97:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR96]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB99:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR98]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB101:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR100]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[WIDE_PTR_PTR97]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP32]], label %[[BOUNDSCHECK_NOTNULL102:.*]], label %[[CONT106:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL102]]: +// CHECK-NEXT: [[TMP33:%.*]] = icmp ult ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_UB99]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT104:.*]], label %[[TRAP103:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP103]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT104]]: +// CHECK-NEXT: [[TMP34:%.*]] = icmp uge ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_LB101]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP34]], label %[[CONT106]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP105]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT106]]: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR97]] +// +struct Outer *foo(int len) { + int * p2 = baz(len); + struct Outer * __single p = bar(len); + p->hdr.len = len; + p->hdr.ptr = p2; + return p; +} + +// CHECK-LABEL: define dso_local ptr @foo2( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP79:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @baz(i32 noundef [[TMP0]]) +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[CALL1:%.*]] = call ptr @bar(i32 noundef [[TMP4]]) +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 +// CHECK-NEXT: [[MUL:%.*]] = mul i64 4, [[CONV]] +// CHECK-NEXT: [[ADD:%.*]] = add i64 16, [[MUL]] +// CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[ADD]], 0 +// CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 [[ADD]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR3]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL1]], ptr [[TMP7]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[P2]], i64 24, i1 false) +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB8]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP9]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END39:.*]], !annotation [[META2]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP21:%.*]] = icmp ule ptr [[WIDE_PTR_LB13]], [[WIDE_PTR_PTR16]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP21]], label %[[LAND_RHS:.*]], label %[[LAND_END39]], !annotation [[META2]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: [[CONV23:%.*]] = sext i32 [[TMP8]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB26]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR29]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i64 [[CONV23]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP34]], label %[[LAND_RHS36:.*]], label %[[LAND_END:.*]], !annotation [[META2]] +// CHECK: [[LAND_RHS36]]: +// CHECK-NEXT: [[CMP37:%.*]] = icmp sle i32 0, [[TMP8]], !annotation [[META2]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META2]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, %[[LAND_RHS]] ], [ [[CMP37]], %[[LAND_RHS36]] ] +// CHECK-NEXT: br label %[[LAND_END39]], !annotation [[META2]] +// CHECK: [[LAND_END39]]: +// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[TMP9]], %[[LAND_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP41]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR43:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR42]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB45:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR44]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB47:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR46]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR43]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label %[[FLEX_BASE_NONNULL:.*]], label %[[CONT68:.*]], !annotation [[META4]] +// CHECK: [[FLEX_BASE_NONNULL]]: +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_OUTER:%.*]], ptr [[WIDE_PTR_PTR43]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[WIDE_PTR_PTR43]], [[TMP11]], !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT49:.*]], label %[[TRAP48:.*]], !prof [[PROF3]], !annotation [[META5]] +// CHECK: [[TRAP48]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: [[CONT49]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR52]], i64 1 +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB54]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT58:.*]], label %[[TRAP57:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP57]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT58]]: +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_LB56]], [[WIDE_PTR_PTR52]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT60:.*]], label %[[TRAP59:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP59]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT60]]: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR52]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP8]], !annotation [[META8]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label %[[CONT62:.*]], label %[[TRAP61:.*]], !prof [[PROF3]], !annotation [[META8]] +// CHECK: [[TRAP61]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META8]] +// CHECK-NEXT: unreachable, !annotation [[META8]] +// CHECK: [[CONT62]]: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB45]], !annotation [[META9]] +// CHECK-NEXT: br i1 [[TMP16]], label %[[CONT64:.*]], label %[[TRAP63:.*]], !prof [[PROF3]], !annotation [[META9]] +// CHECK: [[TRAP63]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: [[CONT64]]: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR43]], [[WIDE_PTR_LB47]], !annotation [[META10]] +// CHECK-NEXT: br i1 [[TMP17]], label %[[CONT66:.*]], label %[[TRAP65:.*]], !prof [[PROF3]], !annotation [[META10]] +// CHECK: [[TRAP65]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META10]] +// CHECK-NEXT: unreachable, !annotation [[META10]] +// CHECK: [[CONT66]]: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB45]] to i64, !annotation [[META11]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META11]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP8]] to i64, !annotation [[META11]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label %[[CONT68]], label %[[TRAP67:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP67]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT68]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR70:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR69]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB72:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR71]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = icmp ne ptr [[WIDE_PTR_PTR70]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT78:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP19:%.*]] = icmp ult ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_UB72]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP19]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP75]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT76]]: +// CHECK-NEXT: [[TMP20:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT78]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP77]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT78]]: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[P]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP79]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR81:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR80]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB83:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR82]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB85:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR84]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP21]], i32 0, i32 0 +// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR81]], ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR86:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP22]], i32 0, i32 0 +// CHECK-NEXT: [[LEN87:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR86]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN87]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[TMP23]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP24]], label %[[BOUNDSCHECK_NOTNULL89:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL89]]: +// CHECK-NEXT: [[FAM90:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY91:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM90]], i64 0, i64 0 +// CHECK-NEXT: [[HDR92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 +// CHECK-NEXT: [[LEN93:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR92]], i32 0, i32 1 +// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[LEN93]], align 8 +// CHECK-NEXT: [[IDX_EXT94:%.*]] = sext i32 [[TMP25]] to i64 +// CHECK-NEXT: [[ADD_PTR95:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY91]], i64 [[IDX_EXT94]] +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR95]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP28]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP31]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR96:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR97:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR96]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB99:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR98]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB101:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR100]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[WIDE_PTR_PTR97]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP32]], label %[[BOUNDSCHECK_NOTNULL102:.*]], label %[[CONT106:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL102]]: +// CHECK-NEXT: [[TMP33:%.*]] = icmp ult ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_UB99]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT104:.*]], label %[[TRAP103:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP103]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT104]]: +// CHECK-NEXT: [[TMP34:%.*]] = icmp uge ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_LB101]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP34]], label %[[CONT106]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP105]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT106]]: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR97]] +// +struct Outer *foo2(int len) { + int * p2 = baz(len); + struct Outer * __single p = bar(len); + p->hdr.ptr = p2; + p->hdr.len = len; + return p; +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META5]] = !{!"bounds-safety-check-one-past-end-overflow"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META7]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META8]] = !{!"bounds-safety-check-count-negative"} +// CHECK: [[META9]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[META10]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META11]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O2.c new file mode 100644 index 0000000000000..c33dced3d3f09 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/flexible-array-member-shared-decls-O2.c @@ -0,0 +1,136 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + + +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +#include + +struct Inner { + int * __counted_by(len) ptr; + int len; +}; +struct Outer { + struct Inner hdr; + int fam[__counted_by(hdr.len)]; +}; + +struct Outer * __sized_by(sizeof(struct Outer) + sizeof(int) * len) bar(int len); +int * __counted_by(len) baz(int len); + +// CHECK-LABEL: define dso_local ptr @foo( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @baz(i32 noundef [[LEN]]) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN]] to i64 +// CHECK-NEXT: [[CALL1:%.*]] = tail call ptr @bar(i32 noundef [[LEN]]) #[[ATTR4]] +// CHECK-NEXT: [[MUL:%.*]] = shl nsw i64 [[IDX_EXT]], 2, !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[LEN]], -5 +// CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL1]], i64 [[MUL]] +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr i8, ptr [[TMP0]], i64 16 +// CHECK-NEXT: [[CMP9_NOT:%.*]] = icmp slt i32 [[LEN]], 0, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP9_NOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !annotation [[META4]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[CALL1]], null, !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT69:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] +// CHECK: [[FLEX_BASE_NONNULL]]: +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[CALL1]], i64 16 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[CALL1]], [[TMP1]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: [[DOTNOT106:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT106]], !annotation [[META8]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP]], label %[[CONT60:.*]], !prof [[PROF9:![0-9]+]], !annotation [[META7]] +// CHECK: [[CONT60]]: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[ADD_PTR3]] to i64, !annotation [[META10:![0-9]+]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[TMP1]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[FLEX_AVAIL_COUNT]], 2, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[CALL1]], [[ADD_PTR3]], !annotation [[META8]] +// CHECK-NEXT: [[OR_COND108:%.*]] = select i1 [[FLEX_COUNT_CHECK_NOT]], i1 [[TMP2]], i1 false, !annotation [[META6]] +// CHECK-NEXT: br i1 [[OR_COND108]], label %[[CONT69]], label %[[TRAP]], !prof [[PROF11:![0-9]+]], !annotation [[META10]] +// CHECK: [[CONT69]]: +// CHECK-NEXT: [[LEN70:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN70]], align 8, !tbaa [[TBAA12:![0-9]+]] +// CHECK-NEXT: store ptr [[CALL]], ptr [[CALL1]], align 8, !tbaa [[TBAA19:![0-9]+]] +// CHECK-NEXT: ret ptr [[CALL1]] +// +struct Outer *foo(int len) { + int * p2 = baz(len); + struct Outer * __single p = bar(len); + p->hdr.len = len; + p->hdr.ptr = p2; + return p; +} + +// CHECK-LABEL: define dso_local ptr @foo2( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[CALL:%.*]] = tail call ptr @baz(i32 noundef [[LEN]]) #[[ATTR4]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN]] to i64 +// CHECK-NEXT: [[CALL1:%.*]] = tail call ptr @bar(i32 noundef [[LEN]]) #[[ATTR4]] +// CHECK-NEXT: [[MUL:%.*]] = shl nsw i64 [[IDX_EXT]], 2, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[LEN]], -5 +// CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL1]], i64 [[MUL]] +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr i8, ptr [[TMP0]], i64 16 +// CHECK-NEXT: [[CMP9_NOT:%.*]] = icmp slt i32 [[LEN]], 0, !annotation [[META4]] +// CHECK-NEXT: br i1 [[CMP9_NOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !annotation [[META4]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[CALL1]], null, !annotation [[META6]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT69:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] +// CHECK: [[FLEX_BASE_NONNULL]]: +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[CALL1]], i64 16 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[CALL1]], [[TMP1]], !annotation [[META7]] +// CHECK-NEXT: [[DOTNOT106:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8]] +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT106]], !annotation [[META8]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP]], label %[[CONT60:.*]], !prof [[PROF9]], !annotation [[META7]] +// CHECK: [[CONT60]]: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[ADD_PTR3]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[TMP1]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[FLEX_AVAIL_COUNT]], 2, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[CALL1]], [[ADD_PTR3]], !annotation [[META8]] +// CHECK-NEXT: [[OR_COND108:%.*]] = select i1 [[FLEX_COUNT_CHECK_NOT]], i1 [[TMP2]], i1 false, !annotation [[META6]] +// CHECK-NEXT: br i1 [[OR_COND108]], label %[[CONT69]], label %[[TRAP]], !prof [[PROF11]], !annotation [[META10]] +// CHECK: [[CONT69]]: +// CHECK-NEXT: store ptr [[CALL]], ptr [[CALL1]], align 8, !tbaa [[TBAA19]] +// CHECK-NEXT: [[LEN78:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN78]], align 8, !tbaa [[TBAA12]] +// CHECK-NEXT: ret ptr [[CALL1]] +// +struct Outer *foo2(int len) { + int * p2 = baz(len); + struct Outer * __single p = bar(len); + p->hdr.ptr = p2; + p->hdr.len = len; + return p; +} +//. +// CHECK: [[META2]] = !{[[META3:![0-9]+]]} +// CHECK: [[META3]] = !{!"bounds-safety-missed-optimization-nuw", !"Check can not be removed because the arithmetic operation might wrap in the unsigned sense. Optimize the check by adding conditions to check for overflow before doing the operation"} +// CHECK: [[META4]] = !{!"bounds-safety-generic"} +// CHECK: [[META5]] = !{!"bounds-safety-generic", !"bounds-safety-check-one-past-end-overflow", !"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-check-count-negative", !"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META7]] = !{!"bounds-safety-check-one-past-end-overflow"} +// CHECK: [[META8]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[PROF9]] = !{!"branch_weights", i32 12286, i32 -12288} +// CHECK: [[META10]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[PROF11]] = !{!"branch_weights", i32 -8193, i32 8190} +// CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META18:![0-9]+]], i64 8} +// CHECK: [[META13]] = !{!"Inner", [[META14:![0-9]+]], i64 0, [[META18]], i64 8} +// CHECK: [[META14]] = !{!"p1 int", [[META15:![0-9]+]], i64 0} +// CHECK: [[META15]] = !{!"any pointer", [[META16:![0-9]+]], i64 0} +// CHECK: [[META16]] = !{!"omnipotent char", [[META17:![0-9]+]], i64 0} +// CHECK: [[META17]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[META18]] = !{!"int", [[META16]], i64 0} +// CHECK: [[TBAA19]] = !{[[META13]], [[META14]], i64 0} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array-counted.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array-counted.c new file mode 100644 index 0000000000000..4eb3bf102e5df --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array-counted.c @@ -0,0 +1,50 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o /dev/null +#include + +extern unsigned externArray[__counted_by(10)]; + +void bar(const unsigned *pointer); + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr @externArray, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr getelementptr inbounds (i32, ptr @externArray, i64 10), ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr @externArray, ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo(void){ + bar(externArray); +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array.c new file mode 100644 index 0000000000000..d5a31c51d100b --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/incomplete-array.c @@ -0,0 +1,53 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm -Werror -verify=werr %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -verify=default -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -Werror -verify=werr %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -verify=default -o /dev/null + +// wno-no-diagnostics +extern unsigned externArray[]; + +void bar(const unsigned *pointer); + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr @externArray, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr @externArray, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr @externArray, ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo(void){ + // default-warning@+1{{accessing elements of an unannotated incomplete array always fails at runtime}} + bar(externArray); // werr-error{{accessing elements of an unannotated incomplete array always fails at runtime}} +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-signed.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-signed.c new file mode 100644 index 0000000000000..525215dce2688 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-signed.c @@ -0,0 +1,53 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -fshort-enums -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -fshort-enums -emit-llvm %s -o - | FileCheck %s + +#include + +enum bar { + bar_val = -1 +}; + +// CHECK-LABEL: @baz( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[B:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[TMP0]] to i8 +// CHECK-NEXT: store i8 [[CONV]], ptr [[B]], align 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[B]], align 1 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i8 [[TMP1]] to i64 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[TMP2]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP2]], align 4 +// CHECK-NEXT: ret i32 [[TMP5]] +// +int baz(int i) { + int *__bidi_indexable ptr; + enum bar b = i; + return ptr[b]; +} + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-unsigned.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-unsigned.c new file mode 100644 index 0000000000000..ff287ee7f770f --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-enum-unsigned.c @@ -0,0 +1,52 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -fshort-enums -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -fshort-enums -emit-llvm %s -o - | FileCheck %s + +#include + +enum bar { + bar_val = 1 +}; + +// CHECK-LABEL: @baz( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[B:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[TMP0]] to i8 +// CHECK-NEXT: store i8 [[CONV]], ptr [[B]], align 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[B]], align 1 +// CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[TMP1]] to i64 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[TMP2]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP2]], align 4 +// CHECK-NEXT: ret i32 [[TMP5]] +// +int baz(int i) { + int *__bidi_indexable ptr; + enum bar b = i; + return ptr[b]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/index-signed.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-signed.c new file mode 100644 index 0000000000000..c880484be0d84 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-signed.c @@ -0,0 +1,49 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[SIGNED_IDX:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[SIGNED_IDX]], align 2 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i16 [[TMP0]] to i64 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[TMP1]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4 +// CHECK-NEXT: ret i32 0 +// +int main() { + int *__bidi_indexable ptr; + + short signed_idx; + ptr[signed_idx]; + return 0; +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/index-unsigned.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-unsigned.c new file mode 100644 index 0000000000000..59280312f55a8 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/index-unsigned.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[UNSIGNED_IDX:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: store i16 5, ptr [[UNSIGNED_IDX]], align 2 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[UNSIGNED_IDX]], align 2 +// CHECK-NEXT: [[IDXPROM:%.*]] = zext i16 [[TMP0]] to i64 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[TMP1]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4 +// CHECK-NEXT: ret i32 0 +// +int main() { + int *__bidi_indexable ptr; + + unsigned short unsigned_idx = 5; + ptr[unsigned_idx]; +} + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/indexable-arithmetic.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/indexable-arithmetic.c new file mode 100644 index 0000000000000..cf5b8cb7efc65 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/indexable-arithmetic.c @@ -0,0 +1,51 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +#include + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[PTR:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP1]], i64 4 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP10:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP11:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// +int *foo(int *__bidi_indexable ptr) { + return &ptr[4]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/large-array-subscript-x86_64.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/large-array-subscript-x86_64.c new file mode 100644 index 0000000000000..b5fea2b6a9aba --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/large-array-subscript-x86_64.c @@ -0,0 +1,87 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +// XXX: Previously, rdar://132269322 was caused by incorrectly emitting 'align 16' here +// CHECK-LABEL: define dso_local float @large_array_subscript( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARR:%.*]] = alloca [80 x float], align 16 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARR]], i8 0, i64 320, i1 false) +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [80 x float], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[ARRAYDECAY]], i64 80 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr float, ptr [[ARRAYDECAY]], i64 19 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARRAYDECAY]], !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP1]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret float [[TMP2]] +// +float large_array_subscript(void) { + float arr[80] = {0}; + return arr[19]; +} + +// CHECK-LABEL: define dso_local float @vla_subscript( +// CHECK-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: [[VLA:%.*]] = alloca float, i64 [[TMP1]], align 16 +// CHECK-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[VLA]], i64 [[TMP1]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[VLA]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[VLA]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr float, ptr [[WIDE_PTR_PTR]], i64 19 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP9]]) +// CHECK-NEXT: ret float [[TMP8]] +// +float vla_subscript(int size) { + float arr[size]; + return arr[19]; +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/member-expr.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/member-expr.c new file mode 100644 index 0000000000000..c2dd383489334 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/member-expr.c @@ -0,0 +1,999 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +#include + +struct foo { + int bar; + int baz; + int frob[10]; +}; + +void escape_ptr_single(int *__single p); +void escape_ptr_bidi(int *__bidi_indexable p); + +// CHECK-LABEL: @foo_single_bar_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_single_bar_single(struct foo *__single f) { + escape_ptr_single(&f->bar); +} + +// CHECK-LABEL: @foo_single_baz_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_single_baz_single(struct foo *__single f) { + escape_ptr_single(&f->baz); +} + +// CHECK-LABEL: @foo_single_frob_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_single_frob_single(struct foo *__single f) { + escape_ptr_single(f->frob); +} + +// CHECK-LABEL: @foo_single_frob4_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 4 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_single_frob4_single(struct foo *__single f) { + escape_ptr_single(&f->frob[4]); +} + +// CHECK-LABEL: @foo_single_bar_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_single_bar_bidi(struct foo *__single f) { + escape_ptr_bidi(&f->bar); +} + +// CHECK-LABEL: @foo_single_baz_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_single_baz_bidi(struct foo *__single f) { + escape_ptr_bidi(&f->baz); +} + +// CHECK-LABEL: @foo_single_frob_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_single_frob_bidi(struct foo *__single f) { + escape_ptr_bidi(f->frob); +} + +// CHECK-LABEL: @foo_single_frob4_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[F:%.*]], ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO:%.*]], ptr [[TMP0]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 4 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_single_frob4_bidi(struct foo *__single f) { + escape_ptr_bidi(&f->frob[4]); +} + +// CHECK-LABEL: @foo_bidi_bar_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont11: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont13: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: ret void +// +void foo_bidi_bar_single(struct foo *__bidi_indexable f) { + escape_ptr_single(&f->bar); +} + +// CHECK-LABEL: @foo_bidi_baz_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont11: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont13: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: ret void +// +void foo_bidi_baz_single(struct foo *__bidi_indexable f) { + escape_ptr_single(&f->baz); +} + +// CHECK-LABEL: @foo_bidi_frob_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont11: +// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont13: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: ret void +// +void foo_bidi_frob_single(struct foo *__bidi_indexable f) { + escape_ptr_single(f->frob); +} + +// CHECK-LABEL: @foo_bidi_frob4_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP7]], i64 4 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap10: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont11: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap12: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont13: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: ret void +// +void foo_bidi_frob4_single(struct foo *__bidi_indexable f) { + escape_ptr_single(&f->frob[4]); +} + +// CHECK-LABEL: @foo_bidi_bar_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_bidi_bar_bidi(struct foo *__bidi_indexable f) { + escape_ptr_bidi(&f->bar); +} + +// CHECK-LABEL: @foo_bidi_baz_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_bidi_baz_bidi(struct foo *__bidi_indexable f) { + escape_ptr_bidi(&f->baz); +} + +// CHECK-LABEL: @foo_bidi_frob_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_bidi_frob_bidi(struct foo *__bidi_indexable f) { + escape_ptr_bidi(f->frob); +} + +// CHECK-LABEL: @foo_bidi_frob4_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[F:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP7]], i64 4 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_bidi_frob4_bidi(struct foo *__bidi_indexable f) { + escape_ptr_bidi(&f->frob[4]); +} + +// CHECK-LABEL: @foo_dot_bar_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 0 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_dot_bar_single(void) { + struct foo f; + escape_ptr_single(&f.bar); +} + +// CHECK-LABEL: @foo_dot_baz_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_dot_baz_single(void) { + struct foo f; + escape_ptr_single(&f.baz); +} + +// CHECK-LABEL: @foo_dot_frob_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_dot_frob_single(void) { + struct foo f; + escape_ptr_single(f.frob); +} + +// CHECK-LABEL: @foo_dot_frob4_single( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 4 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) +// CHECK-NEXT: ret void +// +void foo_dot_frob4_single(void) { + struct foo f; + escape_ptr_single(&f.frob[4]); +} + +// CHECK-LABEL: @foo_dot_bar_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 0 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_dot_bar_bidi(void) { + struct foo f; + escape_ptr_bidi(&f.bar); +} + +// CHECK-LABEL: @foo_dot_baz_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_dot_baz_bidi(void) { + struct foo f; + escape_ptr_bidi(&f.baz); +} + +// CHECK-LABEL: @foo_dot_frob_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_dot_frob_bidi(void) { + struct foo f; + escape_ptr_bidi(f.frob); +} + +// CHECK-LABEL: @foo_dot_frob4_bidi( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 +// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[FROB:%.*]] = getelementptr inbounds nuw [[STRUCT_FOO]], ptr [[F]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[FROB]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 4 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) +// CHECK-NEXT: ret void +// +void foo_dot_frob4_bidi(void) { + struct foo f; + escape_ptr_bidi(&f.frob[4]); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/multiple-dependees.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/multiple-dependees.c new file mode 100644 index 0000000000000..7daae4a7ffbdf --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/multiple-dependees.c @@ -0,0 +1,166 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 %s -O0 -fbounds-safety -triple x86_64 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple x86_64 -emit-llvm -o - | FileCheck %s + +#include + +struct T { + int cnt1; + int cnt2; + int *__counted_by(2 * cnt1 + 3 * cnt2) ptr; +}; + +// CHECK-LABEL: @Foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ARR:%.*]] = alloca [16 x i32], align 16 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_T:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca [[STRUCT_T]], align 8 +// CHECK-NEXT: store i32 [[IDX:%.*]], ptr [[IDX_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARR]], i8 0, i64 64, i1 false) +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [16 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 16 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[CNT1:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 +// CHECK-NEXT: store i32 0, ptr [[CNT1]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CNT2:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 1 +// CHECK-NEXT: store i32 0, ptr [[CNT2]], align 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[PTR1]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END29:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB8:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP9]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR11:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB13:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB15:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP16:%.*]] = icmp ule ptr [[WIDE_PTR_LB8]], [[WIDE_PTR_PTR11]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP16]], label [[LAND_RHS:%.*]], label [[LAND_END29]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP17]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB19:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR18]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB19]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR22]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP27:%.*]] = icmp sle i64 16, [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS28:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.rhs28: +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ false, [[LAND_RHS]] ], [ true, [[LAND_RHS28]] ] +// CHECK-NEXT: br label [[LAND_END29]], {{!annotation ![0-9]+}} +// CHECK: land.end29: +// CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP3]], [[LAND_END]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[CNT130:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 +// CHECK-NEXT: store i32 5, ptr [[CNT130]], align 8 +// CHECK-NEXT: [[CNT231:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 1 +// CHECK-NEXT: store i32 2, ptr [[CNT231]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: [[PTR39:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR34]], ptr [[PTR39]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP41]], ptr align 8 [[T]], i64 16, i1 false) +// CHECK-NEXT: [[CNT142:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[AGG_TEMP41]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CNT142]], align 8 +// CHECK-NEXT: [[CNT243:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[AGG_TEMP41]], i32 0, i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[CNT243]], align 4 +// CHECK-NEXT: [[PTR44:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[AGG_TEMP41]], i32 0, i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[PTR44]], align 8 +// CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 2, [[TMP5]] +// CHECK-NEXT: [[MUL45:%.*]] = mul nsw i32 3, [[TMP6]] +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[MUL]], [[MUL45]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[ADD]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[IDX_ADDR]], align 4 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP11]] to i64 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR47]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[TMP12]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT53:%.*]], label [[TRAP52:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap52: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont53: +// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[TMP12]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT55:%.*]], label [[TRAP54:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap54: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont55: +// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP12]], align 4 +// CHECK-NEXT: ret i32 [[TMP15]] +// +int Foo(int idx) { + int arr[16] = { 0 }; + int *ptr = arr; + struct T t; + t.cnt1 = 5; + t.cnt2 = 2; + t.ptr = ptr; + + return t.ptr[idx]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count-O2.c new file mode 100644 index 0000000000000..23f3e7a6dadfa --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count-O2.c @@ -0,0 +1,84 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --version 4 + +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +struct Inner { + int dummy; + int len; +}; + +struct Outer { + struct Inner hdr; + char fam[__counted_by(hdr.len)]; +}; + +// CHECK-LABEL: define dso_local i8 @access( +// CHECK-SAME: ptr noundef readonly captures(address) [[BAR:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 8 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4, !tbaa {{![0-9]+}} +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[FAM]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[FAM]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[ADD_PTR]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[FAM]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP1]], !annotation {{![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT8:%.*]], label [[TRAP:%.*]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], !annotation {{![0-9]+}} +// CHECK-NEXT: unreachable, !annotation {{![0-9]+}} +// CHECK: cont8: +// CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa {{![0-9]+}} +// CHECK-NEXT: ret i8 [[TMP3]] +// +char access(struct Outer *bar, int index) { + return bar->fam[index]; +} + + + +// CHECK-LABEL: define dso_local noundef nonnull ptr @assign( +// CHECK-SAME: ptr noundef readonly captures(none) [[BAR:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[BAR]], align 8, !nonnull {{![0-9]+}}, !noundef {{![0-9]+}} +// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 8 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[TMP0]], !annotation {{![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], !annotation {{![0-9]+}} +// CHECK-NEXT: unreachable, !annotation {{![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 16 +// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX]], align 8, !tbaa {{![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[AGG_TEMP1_SROA_3_0_COPYLOAD]], [[AGG_TEMP1_SROA_0_0_COPYLOAD]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 false, !annotation {{![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT18:%.*]], label [[TRAP]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK: cont18: +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation {{![0-9]+}} +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_2_0_COPYLOAD]] to i64, !annotation {{![0-9]+}} +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation {{![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation {{![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT]], [[FLEX_COUNT_INTPTR]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[OR_COND49:%.*]] = select i1 [[FLEX_COUNT_MINUS]], i1 [[FLEX_COUNT_CHECK]], i1 false, !annotation {{![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}} +// CHECK-NEXT: [[OR_COND60:%.*]] = select i1 [[OR_COND49]], i1 [[TMP3]], i1 false, !annotation {{![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND60]], label [[BOUNDSCHECK_CONT:%.*]], label [[TRAP]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[LEN31:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 4 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN31]], align 4, !tbaa {{![0-9]+}} +// CHECK-NEXT: ret ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]] +// +struct Outer * assign(void * __bidi_indexable bar, int len) { + struct Outer * __single s = (struct Outer *) bar; + s->hdr.len = len; + return s; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count.c new file mode 100644 index 0000000000000..b6be10a157cc2 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/nested-struct-member-count.c @@ -0,0 +1,271 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +struct Inner { + int dummy; + int len; +}; + +struct Outer { + struct Inner hdr; + char fam[__counted_by(hdr.len)]; +}; + +// CHECK-LABEL: define dso_local i8 @access( +// CHECK-SAME: ptr noundef [[BAR:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BAR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: store ptr [[BAR]], ptr [[BAR_ADDR]], align 8 +// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BAR_ADDR]], align 8 +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: [[FAM2:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM2]], i64 0, i64 0 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY3]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP9]] to i64 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[WIDE_PTR_PTR5]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ult ptr [[TMP10]], [[WIDE_PTR_UB7]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[TMP10]], [[WIDE_PTR_LB]], !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !annotation [[META3]] +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont9: +// CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP10]], align 1 +// CHECK-NEXT: ret i8 [[TMP13]] +// +char access(struct Outer *bar, int index) { + return bar->fam[index]; +} + + +// CHECK-LABEL: define dso_local ptr @assign( +// CHECK-SAME: ptr noundef [[BAR:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BAR_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[S:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: store ptr [[BAR]], ptr [[BAR_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[BAR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT28:%.*]], !annotation [[META4]] +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_OUTER:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP4]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB14:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR13]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR12]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB14]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !annotation [[META2]] +// CHECK: trap17: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont18: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT20:%.*]], label [[TRAP19:%.*]], !annotation [[META3]] +// CHECK: trap19: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont20: +// CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM]], i64 0, i64 0 +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP3]], !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !annotation [[META6]] +// CHECK: trap21: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont22: +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB7]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !annotation [[META7]] +// CHECK: trap23: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: cont24: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !annotation [[META8]] +// CHECK: trap25: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META8]] +// CHECK-NEXT: unreachable, !annotation [[META8]] +// CHECK: cont26: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, !annotation [[META9:![0-9]+]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, !annotation [[META9]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META9]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP3]] to i64, !annotation [[META9]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT]], !annotation [[META9]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT28]], label [[TRAP27:%.*]], !annotation [[META9]] +// CHECK: trap27: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: cont28: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT38:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_UB32]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT36:%.*]], label [[TRAP35:%.*]], !annotation [[META2]] +// CHECK: trap35: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont36: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT38]], label [[TRAP37:%.*]], !annotation [[META3]] +// CHECK: trap37: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont38: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR30]], ptr [[S]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[S]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP14]], i32 0, i32 0 +// CHECK-NEXT: [[LEN39:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[LEN39]], align 4 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[S]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP15]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL41:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull41: +// CHECK-NEXT: [[FAM42:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP15]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY43:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM42]], i64 0, i64 0 +// CHECK-NEXT: [[HDR44:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP15]], i32 0, i32 0 +// CHECK-NEXT: [[LEN45:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR44]], i32 0, i32 1 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[LEN45]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP17]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY43]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP20]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP23]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[WIDE_PTR_PTR47]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP24]], label [[BOUNDSCHECK_NOTNULL52:%.*]], label [[CONT56:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull52: +// CHECK-NEXT: [[TMP25:%.*]] = icmp ult ptr [[WIDE_PTR_PTR47]], [[WIDE_PTR_UB49]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP25]], label [[CONT54:%.*]], label [[TRAP53:%.*]], !annotation [[META2]] +// CHECK: trap53: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont54: +// CHECK-NEXT: [[TMP26:%.*]] = icmp uge ptr [[WIDE_PTR_PTR47]], [[WIDE_PTR_LB51]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP26]], label [[CONT56]], label [[TRAP55:%.*]], !annotation [[META3]] +// CHECK: trap55: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont56: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR47]] +// +struct Outer * assign(void * __bidi_indexable bar, int len) { + struct Outer * __single s = (struct Outer *) bar; + s->hdr.len = len; + return s; +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META5]] = !{!"bounds-safety-check-one-past-end-overflow"} +// CHECK: [[META6]] = !{!"bounds-safety-check-count-negative"} +// CHECK: [[META7]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[META8]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META9]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O0.c new file mode 100644 index 0000000000000..1741e2a00aaa9 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O0.c @@ -0,0 +1,397 @@ + + +// RUN: %clang_cc1 -fbounds-safety -O0 %s -emit-llvm -o %t-O0.s -opt-record-file %t-O0.opt.yaml -opt-record-format yaml +// RUN: FileCheck --input-file %t-O0.s --check-prefixes IR %s +// RUN: FileCheck --input-file %t-O0.opt.yaml --check-prefixes OPT-REM %s + +#include + +void foo(int* __counted_by(n) array, unsigned n, unsigned idx) { + array[idx] = 42; +} + +int main(int argc, char **argv) { + unsigned n = argc; + int * a; + foo(a, n, argc - 1); +} + +// IR-LABEL: @foo +// ... +// IR: icmp ult {{.*}} !dbg ![[LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB:[0-9]+]] +// IR: br i1 %{{[0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_TRAP]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// IR-NEXT: unreachable, !dbg ![[LT_TRAP_LOC_10_16]], !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_CONT]]: +// IR: icmp uge {{.*}} !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[0-9]+]] +// IR: br i1 %{{[0-9]+}}, label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP2:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_GE_LB]] +// ... +// IR: [[FOO_LABEL_TRAP2]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[GE_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: unreachable, !dbg ![[GE_TRAP_LOC_10_16]], !annotation ![[ANNOT_GE_LB]] + +// IR-LABEL: @main +// IR: entry +// ... +// IR-DAG: call void @llvm.memset{{.*}}, !annotation ![[ANNOT_AUTO_INIT:[0-9]+]] +// IR: icmp ule {{.*}} !dbg ![[LOC_16_5:[0-9]+]] +// IR: br i1 %{{.*}}, label %[[MAIN_LABEL_CONT:[a-z0-9.]+]], label %[[MAIN_LABEL_TRAP_RES:[a-z0-9.]+]], !dbg ![[LOC_16_5]] + +// IR: [[MAIN_LABEL_CONT]]: +// ... +// IR: icmp ule {{.*}} !dbg ![[LOC_16_5]] +// IR: br i1 %{{.*}}, label %[[MAIN_LABEL_CONT2:[a-z0-9.]+]], label %[[MAIN_LABEL_TRAP_RES]], !dbg ![[LOC_16_5]] + +// IR: [[MAIN_LABEL_CONT2]]: +// ... +// IR: %[[WIDTH_CHECK_RES:[a-z0-9_]+]] = icmp ule {{.*}} !dbg ![[LOC_16_5]] +// IR: br label %[[MAIN_LABEL_TRAP_RES]] + +// IR: [[MAIN_LABEL_TRAP_RES]]: +// IR: %[[TRAP_RES:[a-z0-9_]+]] = phi i1 [ false, %[[MAIN_LABEL_CONT]] ], [ false, %entry ], [ %[[WIDTH_CHECK_RES]], %[[MAIN_LABEL_CONT2]] ], !dbg ![[TRAP_LOC_MISSING:[0-9]+]], !annotation ![[ANNOT_CONV_TO_COUNT:[0-9]+]] +// IR: br i1 %[[TRAP_RES]], label {{.*}}, label %[[MAIN_LABEL_TRAP:[a-z0-9.]+]], !dbg ![[LOC_16_5]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_CONV_TO_COUNT]] + +// IR: [[MAIN_LABEL_TRAP]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[TRAP_LOC_16_5:[0-9]+]], !annotation ![[ANNOT_CONV_TO_COUNT]] +// IR-NEXT: unreachable, !dbg ![[TRAP_LOC_16_5]], !annotation ![[ANNOT_CONV_TO_COUNT]] + +// IR-DAG: ![[ANNOT_CONV_TO_COUNT]] = !{!"bounds-safety-generic"} +// IR-DAG: ![[ANNOT_AUTO_INIT]] = !{!"bounds-safety-zero-init"} + +// IR-DAG: ![[LOC_10_16]] = !DILocation(line: 10, column: 16{{.*}}) +// IR-DAG: ![[LT_TRAP_LOC_10_16]] = !DILocation(line: 0, scope: ![[LT_TRAP_INFO_10_16:[0-9]+]], inlinedAt: ![[LOC_10_16]]) +// IR-DAG: ![[LT_TRAP_INFO_10_16]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds" +// IR-DAG: ![[GE_TRAP_LOC_10_16]] = !DILocation(line: 0, scope: ![[GE_TRAP_INFO_10_16:[0-9]+]], inlinedAt: ![[LOC_10_16]]) +// IR-DAG: ![[GE_TRAP_INFO_10_16]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing below bounds" +// +// IR-DAG: ![[LOC_16_5]] = !DILocation(line: 16, column: 5 +// IR-DAG: ![[TRAP_LOC_16_5]] = !DILocation(line: 0, scope: ![[TRAP_INFO_16_5:[0-9]+]], inlinedAt: ![[LOC_16_5]]) +// IR-DAG: ![[TRAP_INFO_16_5]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$" + +// IR-DAG: ![[TRAP_LOC_MISSING]] = !DILocation(line: 0, scope: ![[MAIN_SCOPE:[0-9]+]]) +// IR-DAG: ![[MAIN_SCOPE]] = distinct !DISubprogram(name: "main", {{.*}} line: 13, {{.*}} scopeLine: 13 + +// opt-remarks tests generated using `gen-opt-remarks-check-lines.py` + + +// OPT-REM: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '8' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 10, Column: 16 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-zero-init +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '69' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-generic +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '70' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 15, Column: 11 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-zero-init +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: 'call (LLVM IR ''call'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 9 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '58' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'ptrtoint') +// OPT-REM-NEXT: other (LLVM IR 'ptrtoint') +// OPT-REM-NEXT: other (LLVM IR 'sub') +// OPT-REM-NEXT: other (LLVM IR 'sdiv') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 5 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 12 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: 'other (LLVM IR ''zext'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: 'other (LLVM IR ''phi'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NOT: --- !Analysis diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O2.c new file mode 100644 index 0000000000000..521d644d04033 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-argc-O2.c @@ -0,0 +1,203 @@ + + +// RUN: %clang_cc1 -fbounds-safety -O2 %s -emit-llvm -o %t-O2.s -opt-record-file %t-O2.opt.yaml -opt-record-format yaml +// RUN: FileCheck --input-file %t-O2.s --check-prefixes IR %s +// RUN: FileCheck --input-file %t-O2.opt.yaml --check-prefixes OPT-REM %s + +#include + +void foo(int* __counted_by(n) array, unsigned n, unsigned idx) { + array[idx] = 42; +} + +int main(int argc, char **argv) { + unsigned n = argc; + int * a; + foo(a, n, argc - 1); +} + +// IR-LABEL: @foo +// IR: entry +// IR-NEXT: %[[COUNT_EXT:[a-z0-9.]+]] = zext i32 {{.*}} to i64, !dbg ![[LOC_10_5:[0-9]+]] +// IR-NEXT: %[[UPPER_BOUND:[a-z0-9.]+]] = getelementptr inbounds nuw i32, ptr %[[ARR:[a-z0-9.]+]], i64 %[[COUNT_EXT]], !dbg ![[LOC_10_5]] +// IR-NEXT: %[[IDX_EXT:[a-z0-9.]+]] = zext i32 {{.*}} to i64, !dbg ![[LOC_10_16:[0-9]+]] +// IR-NEXT: %[[PTR:[a-z0-9.]+]] = getelementptr i32, ptr %[[ARR]], i64 %[[IDX_EXT]], !dbg ![[LOC_10_16]] +// IR-NEXT: %[[UPPER_CHECK:[a-z0-9.]+]] = icmp ult ptr %[[PTR]], %[[UPPER_BOUND]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LT_UB:[0-9]+]] +// IR-NEXT: %[[LOWER_CHECK:[a-z0-9.]+]] = icmp uge ptr %[[PTR]], %[[ARR]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[0-9]+]] +// TODO: The condition and branch should also be ANNOT_LT_UB_OR_GT_LB (rdar://109089053) +// IR-NEXT: %[[COND:[a-z0-9.]+]] = and i1 %[[UPPER_CHECK]], %[[LOWER_CHECK]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: br i1 %{{[a-z.0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_TRAP]]: +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB_OR_GE_LB:[0-9]+]] +// ... +// IR: [[FOO_LABEL_CONT]]: +// IR-NEXT: store {{.*}} !dbg ![[LOC_10_16]] +// IR-NEXT: ret + +// IR-LABEL: @main +// IR: entry +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[TRAP_LOC_16_5:[0-9]+]] + +// IR-DAG: ![[LOC_10_5]] = !DILocation(line: 10, column: 5 +// IR-DAG: ![[LOC_10_16]] = !DILocation(line: 10, column: 16 +// IR-DAG: ![[ANNOT_LT_UB]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// IR-DAG: ![[ANNOT_LT_UB_OR_GE_LB]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} + +// opt-rem checks autogenerated by gen-opt-remarks-check-lines.py + +// OPT-REM: --- !Passed +// OPT-REM-NEXT: Pass: inline +// OPT-REM-NEXT: Name: Inlined +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 16, Column: 5 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: '''' +// OPT-REM-NEXT: - Callee: foo +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: - String: ''' inlined into ''' +// OPT-REM-NEXT: - Caller: main +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: - String: '''' +// OPT-REM-NEXT: - String: ' with ' +// OPT-REM-NEXT: - String: '(cost=' +// OPT-REM-NEXT: - Cost: '-15' +// OPT-REM-NEXT: - String: ', threshold=' +// OPT-REM-NEXT: - Threshold: '225' +// OPT-REM-NEXT: - String: ')' +// OPT-REM-NEXT: - String: ' at callsite ' +// OPT-REM-NEXT: - String: main +// OPT-REM-NEXT: - String: ':' +// OPT-REM-NEXT: - Line: '3' +// OPT-REM-NEXT: - String: ':' +// OPT-REM-NEXT: - Column: '5' +// OPT-REM-NEXT: - String: ';' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 10, Column: 16 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-argc-O2.c', +// OPT-REM-NEXT: Line: 16, Column: 5 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM: instructions: +// OPT-REM-NEXT: - String: 'other (LLVM IR ''unreachable'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NOT: --- !Analysis diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O0.c new file mode 100644 index 0000000000000..95b104d1ae7dc --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O0.c @@ -0,0 +1,413 @@ + + +// RUN: %clang_cc1 -fbounds-safety -O0 %s -emit-llvm -o %t-O0.s -opt-record-file %t-O0.opt.yaml -opt-record-format yaml +// RUN: FileCheck --input-file %t-O0.s --check-prefixes IR %s +// RUN: FileCheck --input-file %t-O0.opt.yaml --check-prefixes OPT-REM %s + +#include + +void foo(int* __counted_by(n) array, unsigned n) { + array[6] = 42; +} + +int main() { + unsigned n = 5; + int * a; + foo(a, n); +} + +// IR-LABEL: @foo +// ... +// IR: icmp ult {{.*}} !dbg ![[LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB:[0-9]+]] +// IR: br i1 %{{[0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_TRAP]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// IR-NEXT: unreachable, !dbg ![[LT_TRAP_LOC_10_14]], !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_CONT]]: +// IR: br i1 %{{[0-9]+}}, label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP2:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_GE_LB:[0-9]+]] +// ... +// IR: [[FOO_LABEL_TRAP2]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[GT_TRAP_LOC_10_14:[0-9]+]], !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: unreachable, !dbg ![[GT_TRAP_LOC_10_14]], !annotation ![[ANNOT_GE_LB]] + + +// IR-LABEL: @main +// IR: entry +// ... +// IR-DAG: call void @llvm.memset{{.*}}, !annotation ![[ANNOT_AUTO_INIT:[0-9]+]] +// IR: icmp ule {{.*}} !dbg ![[LOC_16_5:[0-9]+]] +// IR: br i1 %{{.*}}, label %[[MAIN_LABEL_CONT:[a-z0-9.]+]], label %[[MAIN_LABEL_TRAP_RES:[a-z0-9.]+]], !dbg ![[LOC_16_5]] + +// IR: [[MAIN_LABEL_CONT]]: +// ... +// IR: icmp ule {{.*}} !dbg ![[LOC_16_5]] +// IR: br i1 %{{.*}}, label %[[MAIN_LABEL_CONT2:[a-z0-9.]+]], label %[[MAIN_LABEL_TRAP_RES]], !dbg ![[LOC_16_5]] + +// IR: [[MAIN_LABEL_CONT2]]: +// ... +// IR: %[[WIDTH_CHECK_RES:[a-z0-9_]+]] = icmp ule {{.*}} !dbg ![[LOC_16_5]] +// IR: br label %[[MAIN_LABEL_TRAP_RES]] + +// IR: [[MAIN_LABEL_TRAP_RES]]: +// IR: %[[TRAP_RES:[a-z0-9_]+]] = phi i1 [ false, %[[MAIN_LABEL_CONT]] ], [ false, %entry ], [ %[[WIDTH_CHECK_RES]], %[[MAIN_LABEL_CONT2]] ], !dbg ![[TRAP_LOC_MISSING:[0-9]+]], !annotation ![[ANNOT_CONV_TO_COUNT:[0-9]+]] +// IR: br i1 %[[TRAP_RES]], label {{.*}}, label %[[MAIN_LABEL_TRAP:[a-z0-9.]+]], !dbg ![[LOC_16_5]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_CONV_TO_COUNT]] + +// IR: [[MAIN_LABEL_TRAP]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[TRAP_LOC_16_5:[0-9]+]], !annotation ![[ANNOT_CONV_TO_COUNT]] +// IR-NEXT: unreachable, !dbg ![[TRAP_LOC_16_5]], !annotation ![[ANNOT_CONV_TO_COUNT]] + +// IR-DAG: ![[ANNOT_CONV_TO_COUNT]] = !{!"bounds-safety-generic"} +// IR-DAG: ![[ANNOT_AUTO_INIT]] = !{!"bounds-safety-zero-init"} + +// IR-DAG: ![[LOC_10_14]] = !DILocation(line: 10, column: 14{{.*}}) +// IR-DAG: ![[LT_TRAP_LOC_10_14]] = !DILocation(line: 0, scope: ![[LT_TRAP_INFO_10_14:[0-9]+]], inlinedAt: ![[LOC_10_14]]) +// IR-DAG: ![[LT_TRAP_INFO_10_14]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds" +// IR-DAG: ![[GT_TRAP_LOC_10_14]] = !DILocation(line: 0, scope: ![[GT_TRAP_INFO_10_14:[0-9]+]], inlinedAt: ![[LOC_10_14]]) +// IR-DAG: ![[GT_TRAP_INFO_10_14]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing below bounds" +// IR-DAG: ![[LOC_16_5]] = !DILocation(line: 16, column: 5 +// IR-DAG: ![[TRAP_LOC_16_5]] = !DILocation(line: 0, scope: ![[TRAP_INFO_16_5:[0-9]+]], inlinedAt: ![[LOC_16_5]]) +// IR-DAG: ![[TRAP_INFO_16_5]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$" + +// IR-DAG: ![[TRAP_LOC_MISSING]] = !DILocation(line: 0, scope: ![[MAIN_SCOPE:[0-9]+]]) +// IR-DAG: ![[MAIN_SCOPE]] = distinct !DISubprogram(name: "main", {{.*}} line: 13, {{.*}} scopeLine: 13 + +// opt-remarks tests generated using `gen-opt-remarks-check-lines.py` + +// OPT-REM: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '8' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 10, Column: 14 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-zero-init +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '69' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-generic +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '70' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 15, Column: 11 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-zero-init +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: 'call (LLVM IR ''call'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 9 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '58' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'store') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: call (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: other (LLVM IR 'load') +// OPT-REM-NEXT: other (LLVM IR 'ptrtoint') +// OPT-REM-NEXT: other (LLVM IR 'ptrtoint') +// OPT-REM-NEXT: other (LLVM IR 'sub') +// OPT-REM-NEXT: other (LLVM IR 'sdiv') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 5 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 16, Column: 12 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: 'other (LLVM IR ''zext'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '1' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: '' +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: 'other (LLVM IR ''phi'')' +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O0.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NOT: --- !Analysis diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O2.c new file mode 100644 index 0000000000000..736aef8740092 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/opt-remarks/ptr-bounds-const-O2.c @@ -0,0 +1,157 @@ + + +// RUN: %clang_cc1 -fbounds-safety -O2 %s -emit-llvm -o %t-O2.s -opt-record-file %t-O2.opt.yaml -opt-record-format yaml +// RUN: FileCheck --input-file %t-O2.s --check-prefixes IR %s +// RUN: FileCheck --input-file %t-O2.opt.yaml --check-prefixes OPT-REM %s + +#include + +void foo(int* __counted_by(n) array, unsigned n) { + array[6] = 42; +} + +int main() { + unsigned n = 5; + int * a; + foo(a, n); +} + +// IR-LABEL: @foo +// ... +// IR-DAG: icmp ult ptr {{.*}}, !dbg {{.+}}, !annotation ![[ANNOT_LT_UB:[0-9]+]] +// IR-DAG: icmp uge ptr {{%.*}}, !dbg {{.+}}, !annotation ![[ANNOT_GE_LB:[0-9]+]] +// IR: [[OR_COND:%.*]] = and i1 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}, !dbg {{.+}}, !annotation ![[ANNOT_GE_LB]] +// IR: br i1 [[OR_COND]], label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg {{.+}}, !annotation ![[ANNOT_LT_UB]] +// ... +// IR: [[FOO_LABEL_TRAP]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB_AND_GE_LB:[0-9]+]] +// IR-NEXT: unreachable, !dbg ![[LOC_10_14]], !annotation ![[ANNOT_LT_UB_AND_GE_LB]] + + +// IR-LABEL: @main +// ... +// IR: tail call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LOC_0:[0-9]+]], !annotation ![[ANNOT_LE_UB_AND_CONV_TO_COUNT:[0-9]+]] +// IR-NEXT: unreachable, !dbg ![[LOC_0]], !annotation ![[ANNOT_LE_UB_AND_CONV_TO_COUNT]] + + +// IR-DAG: ![[ANNOT_LT_UB]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// IR-DAG: ![[ANNOT_LT_UB_AND_GE_LB]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} +// IR-DAG: ![[ANNOT_LE_UB_AND_CONV_TO_COUNT]] = !{!"bounds-safety-generic"} + +// opt-remarks tests generated using `gen-opt-remarks-check-lines.py` + +// OPT-REM: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 9, Column: 0 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 10, Column: 14 } +// OPT-REM-NEXT: Function: foo +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-generic +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: AnnotationSummary +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 13, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Annotated ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' instructions with ' +// OPT-REM-NEXT: - type: bounds-safety-total-summary +// OPT-REM-NEXT: ... + +// OPT-REM-NEXT: --- !Analysis +// OPT-REM-NEXT: Pass: annotation-remarks +// OPT-REM-NEXT: Name: BoundsSafetyCheck +// OPT-REM-NEXT: DebugLoc: { File: '{{.*}}ptr-bounds-const-O2.c', +// OPT-REM-NEXT: Line: 0, Column: 0 } +// OPT-REM-NEXT: Function: main +// OPT-REM-NEXT: Args: +// OPT-REM-NEXT: - String: 'Inserted ' +// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - String: ' LLVM IR instruction' +// OPT-REM-NEXT: - String: s +// OPT-REM-NEXT: - String: "\n" +// OPT-REM-NEXT: - String: "used for:\n" +// OPT-REM-NEXT: - String: bounds-safety-generic +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: ... + +// OPT-REM-NOT: --- !Analysis diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith-O2.c new file mode 100644 index 0000000000000..cf1ac5d2170d0 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith-O2.c @@ -0,0 +1,58 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -triple arm64e -O2 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64e -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +struct T { + char *ptr; + int i; + long l; +}; + +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN:%.*]] to i64 +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds i32, ptr [[BUF:%.*]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[IDX_NEG:%.*]] = sub nsw i64 0, [[IDX_EXT]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[BOUND_PTR_ARITH5:%.*]] = getelementptr i32, ptr [[BUF]], i64 [[IDX_NEG]] +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH5]], [[ADD_PTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5]], [[BUF]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT6:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont6: +// CHECK-NEXT: store i32 3, ptr [[BOUND_PTR_ARITH5]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret void +// +void foo(int *buf __counted_by(len), int len) { + int *ptr = len + buf; + ptr = buf - len; + *ptr = 3;; +} + +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = alloca [10 x i32], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[A]]) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: [[ADD_PTR3_I:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 40 +// CHECK-NEXT: [[BOUND_PTR_ARITH5_I:%.*]] = getelementptr i8, ptr [[A]], i64 -40 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH5_I]], [[ADD_PTR3_I]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5_I]], [[A]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[FOO_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap.i: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: foo.exit: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[A]]) #[[ATTR4]] +// CHECK-NEXT: ret i32 0 +// +int main() { + int a[10]; + foo(a, 10); + return 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith.c new file mode 100644 index 0000000000000..b27efdfda205c --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/ptr-arith.c @@ -0,0 +1,143 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +struct T { + char *ptr; + int i; + long l; +}; + +// +__attribute__((noinline)) +// CHECK-LABEL: @foo( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[BUF:%.*]], ptr [[BUF_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[BUF_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP7]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[BUF_ADDR]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[IDX_EXT2:%.*]] = sext i32 [[TMP17]] to i64 +// CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i64 [[IDX_EXT2]] +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR3]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[IDXPROM4:%.*]] = sext i32 [[TMP15]] to i64 +// CHECK-NEXT: [[IDX_NEG:%.*]] = sub i64 0, [[IDXPROM4]] +// CHECK-NEXT: [[BOUND_PTR_ARITH5:%.*]] = getelementptr i32, ptr [[TMP22]], i64 [[IDX_NEG]] +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH5]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 +// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 +// CHECK-NEXT: [[TMP28:%.*]] = load ptr, ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP28]], ptr [[TMP29]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP30]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP31:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP31]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap6: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont7: +// CHECK-NEXT: store i32 3, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-NEXT: ret void +// +void foo(int *buf __counted_by(len), int len) { + int *ptr = len + buf; + ptr = buf - len; + *ptr = 3;; +} + +// +// XXX: Room for optimizing O0 codegen + + +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[A:%.*]] = alloca [10 x i32], align 16 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR]], i32 noundef 10) +// CHECK-NEXT: ret i32 0 +// +int main() { + int a[10]; + foo(a, 10); + return 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound-lower.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound-lower.c new file mode 100644 index 0000000000000..1296026b7dbdf --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound-lower.c @@ -0,0 +1,134 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-ARM-O2 %s +// RUN: %clang_cc1 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple arm -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-ARM-O2 %s + +#include +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O0-NEXT: [[UPTR:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[BPTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[UPTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[UPTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[UPTR]], i64 16, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB5]], ptr [[TMP7]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[BPTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP10]], i64 -1 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-O0-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK-O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// CHECK-O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP16]], ptr [[TMP17]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[BPTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-O0-NEXT: [[TMP18:%.*]] = icmp ult ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP18]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap13: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont14: +// CHECK-O0-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP19]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap15: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont16: +// CHECK-O0-NEXT: [[TMP20:%.*]] = load i32, ptr [[WIDE_PTR_PTR8]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP20]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3:[0-9]+]] +// CHECK-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 40 +// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -4 +// CHECK-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: br i1 [[OR_COND]], label [[CONT14:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O2: trap: +// CHECK-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O2: cont14: +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3]] +// CHECK-O2-NEXT: ret i32 undef +// +// CHECK-ARM-O2-LABEL: @main( +// CHECK-ARM-O2-NEXT: entry: +// CHECK-ARM-O2-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-ARM-O2-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3:[0-9]+]] +// CHECK-ARM-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i32 40 +// CHECK-ARM-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i32 -4 +// CHECK-ARM-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2-NEXT: br i1 [[OR_COND]], label [[CONT14:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2: trap: +// CHECK-ARM-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-ARM-O2: cont14: +// CHECK-ARM-O2-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3]] +// CHECK-ARM-O2-NEXT: ret i32 undef +// +int main() { + int arr[10]; + int *__indexable uPtr = arr; + int *__bidi_indexable bptr = uPtr; + --bptr; + return *bptr; // trap : underflow +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound.c new file mode 100644 index 0000000000000..35f6ed61068f2 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/array-to-bound.c @@ -0,0 +1,92 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +#include + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR:%.*]], i64 4 +// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 40 +// O2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[ARR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND]], label [[CONT11:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2: trap: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// O2: cont11: +// O2-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP3]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[ARR_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[UPTR:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// O0-NEXT: [[BPTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// O0-NEXT: store ptr [[ARR:%.*]], ptr [[ARR_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARR_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[UPTR]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[UPTR]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[UPTR]], i64 16, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 0 +// O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 1 +// O0-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BPTR]], i32 0, i32 2 +// O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP5]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[UPTR]], i64 16, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR4:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR3]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB6:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR5]], align 8 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// O0-NEXT: store ptr [[WIDE_PTR_UB6]], ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 +// O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 +// O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont: +// O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[CONT12:%.*]], label [[TRAP11:%.*]], {{!annotation ![0-9]+}} +// O0: trap11: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont12: +// O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// O0-NEXT: ret i32 [[TMP12]] +// +int foo(int * arr) { + int *__indexable uPtr = arr; + int *__bidi_indexable bptr = uPtr; +bingo: + return uPtr[10]; // trap : overflow +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array-ok.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array-ok.c new file mode 100644 index 0000000000000..64fa2c567c794 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array-ok.c @@ -0,0 +1,89 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s + +#include + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: br label [[BINGO:%.*]] +// CHECK-O0: bingo: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[P]], i64 16, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR4:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR3]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB6:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB6]], ptr [[TMP7]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap13: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont14: +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap15: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont16: +// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 0 +// +int main() { + int arr[10] = {0}; + int *__indexable p = arr; +bingo:; + return p[9]; // ok +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array.c new file mode 100644 index 0000000000000..b0f510e08b7b1 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/bound-to-array.c @@ -0,0 +1,86 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s + +#include + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[P]], i64 16, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR4:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR3]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB6:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_UB6]], ptr [[TMP7]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap13: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont14: +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap15: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont16: +// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int arr[10]; + int *__indexable p = arr; + return p[10]; // trap : overflow +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-bound.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-bound.c new file mode 100644 index 0000000000000..737b2bc4ebf81 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-bound.c @@ -0,0 +1,109 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -Wno-bounds-safety-init-list -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +#include + +// O0-LABEL: @main( +// O0-NEXT: entry: +// O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// O0-NEXT: [[I:%.*]] = alloca i32, align 4 +// O0-NEXT: [[DCP:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[BP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// O0-NEXT: store i32 0, ptr [[LEN]], align 4 +// O0-NEXT: store i32 3, ptr [[I]], align 4 +// O0-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[I]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: store ptr [[I]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 +// O0-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0: land.rhs: +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] +// O0-NEXT: br label [[LAND_END]] +// O0: land.end: +// O0-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8 +// O0-NEXT: store ptr [[WIDE_PTR_PTR9]], ptr [[DCP]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: [[TMP6:%.*]] = load ptr, ptr [[DCP]], align 8 +// O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP7]] to i64 +// O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 [[IDX_EXT]] +// O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[BP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// O0-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0: trap21: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont22: +// O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0: trap23: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont24: +// O0-NEXT: [[TMP13:%.*]] = load i32, ptr [[WIDE_PTR_PTR16]], align 4 +// O0-NEXT: ret i32 [[TMP13]] +// +int main() { + int len = 0; + int i = 3; + int *__single __counted_by(len) dcp = &i; +bingo:; + int *bp = dcp; + return *bp; // run-time trap : oob - dereference to zero-bound pointer +} + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-thin.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-thin.c new file mode 100644 index 0000000000000..0423873ff0752 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dep-count-ptr-to-thin.c @@ -0,0 +1,116 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +#include + + +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[LEN_INIT_ADDR:%.*]] = alloca i32, align 4 +// O0-NEXT: [[I:%.*]] = alloca [3 x i32], align 4 +// O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// O0-NEXT: [[DCP:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TP:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store i32 [[LEN_INIT:%.*]], ptr [[LEN_INIT_ADDR]], align 4 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[I]], ptr align 4 @__const.foo.i, i64 12, i1 false) +// O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_INIT_ADDR]], align 4 +// O0-NEXT: store i32 [[TMP0]], ptr [[LEN]], align 4 +// O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [3 x i32], ptr [[I]], i64 0, i64 0 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 3 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 +// O0-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0: land.rhs: +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] +// O0-NEXT: br label [[LAND_END]] +// O0: land.end: +// O0-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8 +// O0-NEXT: store ptr [[WIDE_PTR_PTR9]], ptr [[DCP]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: [[TMP6:%.*]] = load ptr, ptr [[DCP]], align 8 +// O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP7]] to i64 +// O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 [[IDX_EXT]] +// O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8 +// O0-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// O0-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR16]], null, {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT24:%.*]], {{!annotation ![0-9]+}} +// O0: boundscheck.notnull: +// O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0: trap21: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont22: +// O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT24]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0: trap23: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont24: +// O0-NEXT: store ptr [[WIDE_PTR_PTR16]], ptr [[TP]], align 8 +// O0-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TP]], align 8 +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4 +// O0-NEXT: ret i32 [[TMP15]] +// +int foo(int len_init) { + int i[3] = {3}; + int len = len_init; + int *__single __counted_by(len) dcp = i; +bingo:; + int *__single tp = dcp; + + return *tp; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dependent-count-pointer-conversion.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dependent-count-pointer-conversion.c new file mode 100644 index 0000000000000..6049ffb46a9ce --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/dependent-count-pointer-conversion.c @@ -0,0 +1,155 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s + +#include + +// O0-LABEL: @main( +// O0-NEXT: entry: +// O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// O0-NEXT: [[DCP:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TP:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[BP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[ARR]], ptr align 16 @__const.main.arr, i64 40, i1 false) +// O0-NEXT: store i32 5, ptr [[LEN]], align 4 +// O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP3]] to i64 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0: land.rhs: +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] +// O0-NEXT: br label [[LAND_END]] +// O0: land.end: +// O0-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8 +// O0-NEXT: store ptr [[WIDE_PTR_PTR9]], ptr [[DCP]], align 8 +// O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DCP]], align 8 +// O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP6]] to i64 +// O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i64 [[IDX_EXT]] +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP8]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP5]], ptr [[TMP9]], align 8 +// O0-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// O0-NEXT: [[TMP10:%.*]] = icmp ne ptr [[WIDE_PTR_PTR16]], null, {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP10]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT24:%.*]], {{!annotation ![0-9]+}} +// O0: boundscheck.notnull: +// O0-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0: trap21: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont22: +// O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT24]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0: trap23: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont24: +// O0-NEXT: store ptr [[WIDE_PTR_PTR16]], ptr [[TP]], align 8 +// O0-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DCP]], align 8 +// O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[IDX_EXT25:%.*]] = sext i32 [[TMP14]] to i64 +// O0-NEXT: [[ADD_PTR26:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 [[IDX_EXT25]] +// O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP13]], ptr [[TMP15]], align 8 +// O0-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR26]], ptr [[TMP16]], align 8 +// O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP13]], ptr [[TMP17]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[BP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8 +// O0-NEXT: [[TMP18:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR29]], i64 5 +// O0-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8 +// O0-NEXT: [[TMP19:%.*]] = icmp ult ptr [[TMP18]], [[WIDE_PTR_UB31]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP19]], label [[CONT35:%.*]], label [[TRAP34:%.*]], {{!annotation ![0-9]+}} +// O0: trap34: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont35: +// O0-NEXT: [[TMP20:%.*]] = icmp uge ptr [[TMP18]], [[WIDE_PTR_LB33]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP20]], label [[CONT37:%.*]], label [[TRAP36:%.*]], {{!annotation ![0-9]+}} +// O0: trap36: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont37: +// O0-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP18]], align 4 +// O0-NEXT: ret i32 [[TMP21]] +// +// O2-LABEL: @main( +// O2-NEXT: entry: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable +// +int main() { + int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + int len = 5; + int *__counted_by(len) dcp = arr; + int *__single tp = dcp; // ok: check len >= 1 or dcp is null + int *bp = dcp; // construct bounds pointer based on calculated bounds +bingo:; + return bp[5]; // oob trap! +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/length-check-bound-check-removal.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/length-check-bound-check-removal.c new file mode 100644 index 0000000000000..8a8b032436764 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/length-check-bound-check-removal.c @@ -0,0 +1,86 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 + +// RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck %s +// +#include + +typedef struct { + int *__counted_by(len) buf; + int len; +} S; + +void use(int *, int); + +// CHECK-LABEL: define dso_local range(i32 -1, 1) i32 @access1( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 8, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 2 +// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT11:%.*]] +// CHECK: cont11: +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA9:![0-9]+]] +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA10:![0-9]+]] +// CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH]], i32 noundef [[TMP2]]) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: br label [[CLEANUP]] +// CHECK: cleanup: +// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT11]] ], [ -1, [[ENTRY:%.*]] ] +// CHECK-NEXT: ret i32 [[RETVAL_0]] +// +int access1(S *p) { + int *Ptr = p->buf; + int Len = p->len; + + if (Len < 2) return -1; + int v = *Ptr++; + use(Ptr, v); + return 0; +} + +// CHECK-LABEL: define dso_local range(i32 -1, 1) i32 @access2( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA9]] +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 2 +// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT11:%.*]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META11:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: cont11: +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA10]] +// CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH]], i32 noundef [[TMP2]]) #[[ATTR3]] +// CHECK-NEXT: [[BOUND_PTR_ARITH14:%.*]] = getelementptr i8, ptr [[TMP1]], i64 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[ADD_PTR]], !annotation [[META12:![0-9]+]] +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[TMP1]], !annotation [[META13:![0-9]+]] +// CHECK-NEXT: [[OR_COND35:%.*]] = and i1 [[TMP3]], [[TMP4]], !annotation [[META13]] +// CHECK-NEXT: br i1 [[OR_COND35]], label [[CONT22:%.*]], label [[TRAP:%.*]], !prof [[PROF14:![0-9]+]], !annotation [[META12]] +// CHECK: cont22: +// CHECK-NEXT: [[DOTNOT39:%.*]] = icmp eq ptr [[BOUND_PTR_ARITH14]], null, !annotation [[META15:![0-9]+]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH14]], [[ADD_PTR]], !annotation [[META12]] +// CHECK-NEXT: [[OR_COND40:%.*]] = select i1 [[DOTNOT39]], i1 true, i1 [[TMP5]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[OR_COND40]], label [[CONT32:%.*]], label [[TRAP]], !prof [[PROF16:![0-9]+]], !annotation [[META15]] +// CHECK: cont32: +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, !tbaa [[TBAA10]] +// CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH14]], i32 noundef [[TMP6]]) #[[ATTR3]] +// CHECK-NEXT: br label [[CLEANUP]] +// CHECK: cleanup: +// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT32]] ], [ -1, [[ENTRY:%.*]] ] +// CHECK-NEXT: ret i32 [[RETVAL_0]] +// +int access2(S *p) { + int *Ptr = p->buf; + int Len = p->len; + + if (Len < 2) return -1; + int v = *Ptr++; + use(Ptr, v); + v = *Ptr++; + use(Ptr, v); + return 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript-deref.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript-deref.c new file mode 100644 index 0000000000000..713f084952103 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript-deref.c @@ -0,0 +1,76 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 +// CHECK-O0-NEXT: [[I:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 10 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[I]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[I]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[I]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: br label [[BINGO:%.*]] +// CHECK-O0: bingo: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[I]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int arr[10]; + + int *i = &arr[10]; +bingo:; + return *i; // run-time trap : oob +} + +// + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript.c new file mode 100644 index 0000000000000..207a4d19c4e32 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-array-subscript.c @@ -0,0 +1,74 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR:%.*]], i64 4 +// O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 40 +// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2: trap: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// O2: cont1: +// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP2]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[ARR_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[BIDI_ARR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[I:%.*]] = alloca i32, align 4 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[ARR:%.*]], ptr [[ARR_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARR_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BIDI_ARR]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BIDI_ARR]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BIDI_ARR]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BIDI_ARR]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont: +// O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont2: +// O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// O0-NEXT: store i32 [[TMP6]], ptr [[I]], align 4 +// O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4 +// O0-NEXT: ret i32 [[TMP7]] +// +int foo(int * arr) { + int * bidi_arr = arr; +bingo:; + int i = bidi_arr[10]; + + return i; +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-dependent-count-ptr.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-dependent-count-ptr.c new file mode 100644 index 0000000000000..891160bf3f8ff --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/oob-dependent-count-ptr.c @@ -0,0 +1,78 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=O0 %s +// RUN: %clang_cc1 -O2 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=O2 %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=O0 %s +// RUN: %clang_cc1 -O2 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=O2 %s + +#include + +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[BUF_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[BUF:%.*]], ptr [[BUF_ADDR]], align 8 +// O0-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR]], align 4 +// O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// O0-NEXT: [[TMP1:%.*]] = load ptr, ptr [[BUF_ADDR]], align 8 +// O0-NEXT: [[TMP2:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[IDX_EXT]] +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 5 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[TMP6]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont: +// O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[TMP6]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont2: +// O0-NEXT: store i32 [[TMP0]], ptr [[TMP6]], align 4 +// O0-NEXT: ret void +// +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN:%.*]] to i64 +// O2-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[BUF:%.*]], i64 [[IDX_EXT]] +// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BUF]], i64 20 +// O2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[BUF]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP1]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2: trap: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// O2: cont1: +// O2-NEXT: store i32 [[LEN]], ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret void +// +void foo(int *__counted_by(len) buf, int len) { + buf[5] = len; +} + + + + + + + + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound-ok.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound-ok.c new file mode 100644 index 0000000000000..00f1a999c2eaa --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound-ok.c @@ -0,0 +1,95 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name tmp1 + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s + +// O0-LABEL: @main( +// O0-NEXT: entry: +// O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// O0-NEXT: [[ARR:%.*]] = alloca [4 x i32], align 16 +// O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP1TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// O0-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARR]], i8 0, i64 16, i1 false) +// O0-NEXT: br label [[TEST_START:%.*]] +// O0: test_start: +// O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [4 x i32], ptr [[ARR]], i64 0, i64 0 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 4 +// O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 4 +// O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP1TMP1]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP1TMP1]], i32 0, i32 0 +// O0-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH2:%.*]] = getelementptr i32, ptr [[TMP13]], i64 -1 +// O0-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH2]], ptr [[TMP14]], align 8 +// O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP1TMP1]], i32 0, i32 1 +// O0-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP16]], ptr [[TMP17]], align 8 +// O0-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP1TMP1]], i32 0, i32 2 +// O0-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 +// O0-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP19]], ptr [[TMP20]], align 8 +// O0-NEXT: br label [[TEST_END:%.*]] +// O0: test_end: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP22]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont4: +// O0-NEXT: [[TMP23:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP23]] +// +// O2-LABEL: @main( +// O2-NEXT: entry: +// O2-NEXT: ret i32 0 +// +int main() { + int arr[4] = {0}; +test_start:; + int *p = arr; + p += 4; + p -= 1; +test_end:; + return *p; // ok +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound.c new file mode 100644 index 0000000000000..dcac06d8af2c1 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-compound.c @@ -0,0 +1,73 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [4 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [4 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 4 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 4 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int arr[4]; + int *p = arr; + p += 4; + return *p; // trap +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec-ok.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec-ok.c new file mode 100644 index 0000000000000..2da353f01cb2d --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec-ok.c @@ -0,0 +1,76 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP0]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 -1 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P_COPY]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont2: +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP15]] +// +int foo(int * a) { + int *p = a; + int *p_copy = p--; +bingo:; + return *p_copy; // ok +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec.c new file mode 100644 index 0000000000000..f71f61368d6dd --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postdec.c @@ -0,0 +1,86 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 4 +// O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 +// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2: trap: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// O2: cont1: +// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP2]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 -1 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont: +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont2: +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP15]] +// +int foo(int* a) { + int *p = a; +bingo:; + int *p_copy = p--; + return *p; +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc-ok.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc-ok.c new file mode 100644 index 0000000000000..0f991a96365a3 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc-ok.c @@ -0,0 +1,77 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP0]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 1 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P_COPY]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont: +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable +// O0: cont2: +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP15]] +// +int foo(int* a) { + int *p = a; + int *p_copy = p++; +bingo:; + return *p_copy; +} + + +// diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc.c new file mode 100644 index 0000000000000..73711acf37eb9 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-postinc.c @@ -0,0 +1,75 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 4, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 1 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 1 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int a[1] = {0}; + int *p = a; + int *p_copy = p++; + + return *p; // trap +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec-self.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec-self.c new file mode 100644 index 0000000000000..e6e7b06d5bc5e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec-self.c @@ -0,0 +1,87 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 4, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 1 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 -1 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[A]]) #[[ATTR3:[0-9]+]] +// CHECK-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4 +// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 +// CHECK-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O2: trap: +// CHECK-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O2: cont1: +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[A]]) #[[ATTR3]] +// CHECK-O2-NEXT: ret i32 undef +// +int main() { + int a[1] = {0}; + int *p = a; + int *p_copy = --p; + + return *p; // trap +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec.c new file mode 100644 index 0000000000000..4fdccc0eb0763 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-predec.c @@ -0,0 +1,86 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s + +// O2-LABEL: @foo( +// O2-NEXT: entry: +// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 4 +// O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 +// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2: trap: +// O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// O2: cont1: +// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP2]] +// +// O0-LABEL: @foo( +// O0-NEXT: entry: +// O0-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// O0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8 +// O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[UPPER]], ptr [[TMP2]], align 8 +// O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 -1 +// O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// O0-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// O0-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// O0-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// O0-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// O0-NEXT: br label [[BINGO:%.*]] +// O0: bingo: +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P_COPY]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0: trap: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont: +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0: trap1: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont2: +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP15]] +// +int foo(int * a) { + int *p = a; + int *p_copy = --p; +bingo:; + return *p_copy; +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc-self.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc-self.c new file mode 100644 index 0000000000000..a54760a8cc679 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc-self.c @@ -0,0 +1,77 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 4, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 1 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 1 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int a[1] = {0}; + int *p = a; + int *p_copy = ++p; + + return *p; // trap +} + + diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc.c new file mode 100644 index 0000000000000..36ecb04827b94 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-preinc.c @@ -0,0 +1,75 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 4, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 1 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 1 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P_COPY]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP14]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int main() { + int a[1] = {0}; + int *p = a; + int *p_copy = ++p; + + return *p_copy; // trap +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-prepost.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-prepost.c new file mode 100644 index 0000000000000..b9c92cf21de45 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/runtime-checks/ptr-arith-prepost.c @@ -0,0 +1,90 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[A:%.*]] = alloca [2 x i32], align 4 +// CHECK-O0-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[P_COPY:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP_TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 8, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 2 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[P_COPY]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP4]], i64 1 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP_TMP1]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 +// CHECK-O0-NEXT: [[BOUND_PTR_ARITH2:%.*]] = getelementptr i32, ptr [[TMP13]], i64 1 +// CHECK-O0-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[BOUND_PTR_ARITH2]], ptr [[TMP14]], align 8 +// CHECK-O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// CHECK-O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP16]], ptr [[TMP17]], align 8 +// CHECK-O0-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 +// CHECK-O0-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[P]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP19]], ptr [[TMP20]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P_COPY]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP22]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP23:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP23]] +// +// CHECK-O2-LABEL: @main( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 0 +// +int main() { + int a[2] = {0}; + int *p = a; + int *p_copy = p++; + ++p; + + return *p_copy; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null-O2.c new file mode 100644 index 0000000000000..11fb350fd3384 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null-O2.c @@ -0,0 +1,30 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 + +#include + +// CHECK-O2-LABEL: @TestOK( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 0 +// +int TestOK() { + int len = 0; + int *__single __counted_by(len) dcp = 0; + int *__single tp = dcp; + return 0; +} + +// FIXME +// CHECK-O2-LABEL: @TestTrap( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret void +// +void TestTrap() { + int len = 1; + char p; + char *__counted_by(len) dcp = &p; + int *__single tp = dcp; // rdar://80816535 +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null.c new file mode 100644 index 0000000000000..1a65f3cdc8f49 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/single-null.c @@ -0,0 +1,65 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 + +#include + +// CHECK-O0-LABEL: @main( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[LEN:%.*]] = alloca i32, align 4 +// CHECK-O0-NEXT: [[DCP:%.*]] = alloca ptr, align 8 +// CHECK-O0-NEXT: [[TP:%.*]] = alloca ptr, align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-O0-NEXT: store i32 0, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: store ptr null, ptr [[DCP]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = load ptr, ptr [[DCP]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP2]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[IDX_EXT]] +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: boundscheck.notnull: +// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT4]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont4: +// CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TP]], align 8 +// CHECK-O0-NEXT: ret i32 0 +// +int main() { + int len = 0; + int *__single __counted_by(len) dcp = 0; + int *__single tp = dcp; + return 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call-O2.c new file mode 100644 index 0000000000000..7799147f91326 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call-O2.c @@ -0,0 +1,213 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s + +#include + +void foo(int *__sized_by_or_null(len) p, int len); + +// CHECK-LABEL: define dso_local void @caller_1( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @foo(ptr noundef null, i32 noundef 2) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: ret void +// +void caller_1() { + foo(0, 2); +} + +// CHECK-LABEL: define dso_local void @caller_2( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @foo(ptr noundef null, i32 noundef 0) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_2() { + foo(0, 0); +} + +// rdar://118117905 +// CHECK-LABEL: define dso_local void @caller_3( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[P]], null, !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[CMP_NOT79:%.*]] = icmp slt i32 [[LEN]], 0 +// CHECK-NEXT: [[CMP_NOT:%.*]] = and i1 [[DOTNOT]], [[CMP_NOT79]], !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6:[0-9]+]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_3(int *__sized_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_4( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK-LABEL: define dso_local void @caller_5( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[I]]) #[[ATTR5]] +// CHECK-NEXT: store i32 0, ptr [[I]], align 4, !tbaa [[TBAA4:![0-9]+]] +// CHECK-NEXT: call void @foo(ptr noundef nonnull [[I]], i32 noundef 2) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[I]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK-LABEL: define dso_local void @caller_6( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[LEN]], 0, !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: land.rhs: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// +void caller_6(int *__sized_by(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_7( +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_9_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_9_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_9_0_P_SROA_IDX]], align 8 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP_SROA_9_0_COPYLOAD]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_LHS_TRUE:%.*]], !annotation [[META3]] +// CHECK: land.lhs.true: +// CHECK-NEXT: [[AGG_TEMP_SROA_17_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 +// CHECK-NEXT: [[AGG_TEMP_SROA_17_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_17_0_P_SROA_IDX]], align 8, !tbaa [[TBAA8:![0-9]+]] +// CHECK-NEXT: [[CMP27_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_17_0_COPYLOAD]], [[AGG_TEMP_SROA_0_0_COPYLOAD]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27_NOT]], label [[TRAP]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: land.rhs: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[CONT:%.*]], label [[LOR_RHS:%.*]], !annotation [[META3]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[LEN]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_9_0_COPYLOAD]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META11:![0-9]+]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sge i64 [[SUB_PTR_SUB]], [[CONV]], !annotation [[META3]] +// CHECK-NEXT: [[CMP68:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP68]], [[CMP65]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT]], label [[TRAP]], !prof [[PROF13:![0-9]+]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[AGG_TEMP_SROA_0_0_COPYLOAD]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_8( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[P]], null, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = icmp ult i32 [[LEN]], 5 +// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL_NOT]], [[SPEC_SELECT]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF14:![0-9]+]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont: +// CHECK-NEXT: tail call void @foo(ptr noundef [[P]], i32 noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_8(int *__single p, int len) { + foo(p, len); +} + +void bar(int *__sized_by(*len) *out, int *len); + +// CHECK-LABEL: define dso_local void @caller_9( +// CHECK-SAME: ptr noundef [[OUT:%.*]], ptr noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @bar(ptr noundef [[OUT]], ptr noundef [[LEN]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void caller_9(int *__sized_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK-LABEL: define dso_local ptr @caller_10( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META15:![0-9]+]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META15]] +// CHECK-NEXT: call void @bar(ptr noundef nonnull [[P]], ptr noundef nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA8]] +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[CMP_NOT90:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT90]], i1 false, !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META16:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META16]] +// CHECK: land.rhs: +// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT67:%.*]], !annotation [[META3]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CMP61:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] +// CHECK-NEXT: [[CMP64:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP64]], [[CMP61]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT67]], label [[TRAP]], !prof [[PROF13]], !annotation [[META3]] +// CHECK: cont67: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] +// CHECK-NEXT: ret ptr [[TMP0]] +// +int *__sized_by_or_null(len) caller_10(int len) { + int count; + int *__sized_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} + +//. +// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META3]] = !{!"bounds-safety-generic"} +// CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0} +// CHECK: [[META5]] = !{!"int", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"omnipotent char", [[META7:![0-9]+]], i64 0} +// CHECK: [[META7]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0} +// CHECK: [[META9]] = !{!"p1 int", [[META10:![0-9]+]], i64 0} +// CHECK: [[META10]] = !{!"any pointer", [[META6]], i64 0} +// CHECK: [[META11]] = !{!"bounds-safety-generic", [[META12:![0-9]+]]} +// CHECK: [[META12]] = !{!"bounds-safety-missed-optimization-nsw", !"Check can not be removed because the arithmetic operation might wrap in the signed sense. Optimize the check by adding conditions to check for overflow before doing the operation"} +// CHECK: [[PROF13]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[PROF14]] = !{!"branch_weights", i32 2097151, i32 1} +// CHECK: [[META15]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META16]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call.c new file mode 100644 index 0000000000000..2c717054d57ee --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/sized_by_or_null_call.c @@ -0,0 +1,963 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s + +#include + +void foo(int *__sized_by_or_null(len) p, int len); + +// CHECK-LABEL: define dso_local void @caller_1( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2:![0-9]+]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 2) +// CHECK-NEXT: ret void +// +void caller_1() { + foo(0, 2); +} + +// CHECK-LABEL: define dso_local void @caller_2( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 0) +// CHECK-NEXT: ret void +// +void caller_2() { + foo(0, 0); +} + +// CHECK-LABEL: define dso_local void @caller_3( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP71:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP15]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP18]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs67: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP20:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP19]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.end70: +// CHECK-NEXT: [[TMP21:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP20]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR73]], i32 noundef [[TMP9]]) +// CHECK-NEXT: ret void +// +void caller_3(int *__sized_by_or_null(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_4( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[I]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 +// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR]], i32 noundef -1) +// CHECK-NEXT: ret void +// +void caller_4() { + int i = 0; + foo(&i, -1); +} + +// CHECK-LABEL: define dso_local void @caller_5( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[I]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR]], i32 noundef 2) +// CHECK-NEXT: ret void +// +void caller_5() { + int i = 0; + foo(&i, 2); +} + +// CHECK-LABEL: define dso_local void @caller_6( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP71:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs67: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP15]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.end70: +// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP16]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR73]], i32 noundef [[TMP5]]) +// CHECK-NEXT: ret void +// +void caller_6(int *__sized_by(len) p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_7( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP71:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP4]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs67: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP10]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] +// CHECK: land.end70: +// CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP11]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR73]], i32 noundef [[TMP0]]) +// CHECK-NEXT: ret void +// +void caller_7(int *__bidi_indexable p, int len) { + foo(p, len); +} + +// CHECK-LABEL: define dso_local void @caller_8( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP15:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END36:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP13]], label [[LAND_RHS:%.*]], label [[LAND_END36]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[UPPER16:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[UPPER16]], ptr [[TMP11]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB18]], ptr [[TMP13]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR20]], ptr [[TMP14]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP15]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB24]], ptr [[TMP16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR26]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[CMP31:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP31]], label [[LAND_RHS33:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs33: +// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP34]], [[LAND_RHS33]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP18:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP17]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END36]], !annotation [[META2]] +// CHECK: land.end36: +// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP18]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @foo(ptr noundef [[TMP0]], i32 noundef [[TMP1]]) +// CHECK-NEXT: ret void +// +void caller_8(int *__single p, int len) { + foo(p, len); +} + +void bar(int *__sized_by(*len) *out, int *len); + +// CHECK-LABEL: define dso_local void @caller_9( +// CHECK-SAME: ptr noundef [[OUT:%.*]], ptr noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUT]], ptr [[OUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[LEN]], ptr [[LEN_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUT_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[LEN_ADDR]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP0]], ptr noundef [[TMP1]]) +// CHECK-NEXT: ret void +// +void caller_9(int *__sized_by(*len) *out, int *len){ + bar(out, len); +} + +// CHECK-LABEL: define dso_local ptr @caller_10( +// CHECK-SAME: i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP72:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP79:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META4]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr ptr, ptr [[P]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[P]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[P]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[COUNT]], i64 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[COUNT]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[COUNT]], ptr [[TMP7]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP8]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !annotation [[META6]] +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont4: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL12:%.*]], label [[CONT16:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull12: +// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_UB9]], !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !annotation [[META5]] +// CHECK: trap13: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont14: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT16]], label [[TRAP15:%.*]], !annotation [[META6]] +// CHECK: trap15: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont16: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR7]]) +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP14]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL18:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull18: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP15]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP14]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] +// CHECK: boundscheck.null: +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] +// CHECK: boundscheck.cont: +// CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR21]], [[WIDE_PTR_UB28]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END69:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP39:%.*]] = icmp ule ptr [[WIDE_PTR_LB31]], [[WIDE_PTR_PTR34]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP39]], label [[LAND_RHS:%.*]], label [[LAND_END69]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR42]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP23]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP47]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR53]], ptr [[TMP24]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB55]], ptr [[TMP25]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB57]], ptr [[TMP26]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR59:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR58]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB61:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR60]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB63:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR62]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB49]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR59]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[CMP64:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP64]], label [[LAND_RHS66:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs66: +// CHECK-NEXT: [[CMP67:%.*]] = icmp sle i32 0, [[TMP23]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP27:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP67]], [[LAND_RHS66]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP28:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP27]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END69]], !annotation [[META2]] +// CHECK: land.end69: +// CHECK-NEXT: [[TMP29:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP28]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP29]], label [[CONT71:%.*]], label [[TRAP70:%.*]], !annotation [[META2]] +// CHECK: trap70: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont71: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP72]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR74:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR73]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR75:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB76:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR75]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB78:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR77]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR74]], ptr [[P]], align 8 +// CHECK-NEXT: store i32 [[TMP23]], ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP30:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[TMP30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP32]], label [[BOUNDSCHECK_NOTNULL80:%.*]], label [[BOUNDSCHECK_NULL83:%.*]], !annotation [[META3]] +// CHECK: boundscheck.notnull80: +// CHECK-NEXT: [[IDX_EXT81:%.*]] = sext i32 [[TMP31]] to i64 +// CHECK-NEXT: [[ADD_PTR82:%.*]] = getelementptr inbounds i8, ptr [[TMP30]], i64 [[IDX_EXT81]] +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP33]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR82]], ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP35]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT84:%.*]] +// CHECK: boundscheck.null83: +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP36]], align 8 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP38]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT84]] +// CHECK: boundscheck.cont84: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR86:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR85]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB88:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR87]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB90:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR89]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR86]] +// +int *__sized_by_or_null(len) caller_10(int len) { + int count; + int *__sized_by_or_null(count) p; + bar(&p, &count); + p = p; // workaround for missing return bounds check + count = len; + return p; +} +//. +// CHECK: [[META2]] = !{!"bounds-safety-generic"} +// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META5]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-O2.c new file mode 100644 index 0000000000000..e3d42603aaef4 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-O2.c @@ -0,0 +1,82 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[PTR_COERCE0:%.*]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT2:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[PTR_COERCE1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT2]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP1]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[PTR_COERCE0]] +// +int *__null_terminated indexable(int *__indexable ptr) { + return __unsafe_null_terminated_from_indexable(ptr); +} + +// CHECK-LABEL: @bidi_indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[PTR:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_2_0_PTR_SROA_IDX]], align 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 16 +// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_PTR_SROA_IDX]], align 8, {{!tbaa ![0-9]+}} +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp uge ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_3_0_COPYLOAD]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 [[TMP0]], i1 false, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF13:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT8:%.*]] ], [ [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT8]], !prof [[PROF6]], {{!annotation ![0-9]+}} +// CHECK: cont8: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP1]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]] +// +int *__null_terminated bidi_indexable(int *__bidi_indexable ptr) { + return __unsafe_null_terminated_from_indexable(ptr); +} + +// CHECK-LABEL: @nested_indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[PTR_COERCE0:%.*]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT2:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[PTR_COERCE1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT2]], !prof [[PROF6]], {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR_0]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP1]], inttoptr (i64 -1 to ptr) +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[PTR_COERCE0]] +// +int *__single *__terminated_by(-1) nested_indexable(int *__single *__indexable ptr) { + return __unsafe_terminated_by_from_indexable(-1, ptr); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-trivial-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-trivial-O2.c new file mode 100644 index 0000000000000..4eda5ca5ab4aa --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable-trivial-O2.c @@ -0,0 +1,64 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +static const struct { + int _dummy; + int ints[3]; +} foo = { + 0, + {1, 2, 3}, +}; + +// CHECK-LABEL: @good( +// CHECK-NEXT: cont8.2: +// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @foo, i64 4) +// +const int *__terminated_by(3) good(void) { + const int *__indexable p = foo.ints; + return __unsafe_terminated_by_from_indexable(3, p); +} + +// CHECK-LABEL: @good_2( +// CHECK-NEXT: cont8.1: +// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @foo, i64 4) +// +const int *__terminated_by(2) good_2(void) { + const int *__indexable p = foo.ints; + return __unsafe_terminated_by_from_indexable(2, p); +} + +// CHECK-LABEL: @bad_null( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +int *__null_terminated bad_null(void) { + int *__indexable p = 0; + return __unsafe_null_terminated_from_indexable(p); +} + +// CHECK-LABEL: @bad_no_term( +// CHECK-NEXT: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +const int *__null_terminated bad_no_term(void) { + const int *__indexable p = foo.ints; + return __unsafe_null_terminated_from_indexable(p); +} + +// CHECK-LABEL: @bad_bidi_lower_bound( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +const int *__terminated_by(3) bad_bidi_lower_bound(void) { + // Conversion of __bidi_indexable to __indexable should fail. + const int *__bidi_indexable p = foo.ints; + p--; + return __unsafe_terminated_by_from_indexable(3, p); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable.c new file mode 100644 index 0000000000000..3875730293836 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-from-indexable.c @@ -0,0 +1,150 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[TERMINATED_BY_CUR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { ptr, ptr }, ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[PTR_COERCE0:%.*]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { ptr, ptr }, ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[PTR_COERCE1:%.*]], ptr [[TMP1]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR1]], i64 1 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]] +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont3: +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TERMINATED_BY_CUR1]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP3]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] +// CHECK: terminated_by.loop_cont: +// CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// +int *__null_terminated indexable(int *__indexable ptr) { + return __unsafe_null_terminated_from_indexable(ptr); +} + +// CHECK-LABEL: @bidi_indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TERMINATED_BY_CUR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[PTR:%.*]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap6: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont7: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR8:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR8]], i64 1 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB5]] +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT10:%.*]], label [[TRAP9:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap9: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont10: +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TERMINATED_BY_CUR8]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP4]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] +// CHECK: terminated_by.loop_cont: +// CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR3]] +// +int *__null_terminated bidi_indexable(int *__bidi_indexable ptr) { + return __unsafe_null_terminated_from_indexable(ptr); +} + +// CHECK-LABEL: @nested_indexable( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable.0", align 8 +// CHECK-NEXT: [[TERMINATED_BY_CUR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { ptr, ptr }, ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[PTR_COERCE0:%.*]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { ptr, ptr }, ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[PTR_COERCE1:%.*]], ptr [[TMP1]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] +// CHECK: terminated_by.loop_cond: +// CHECK-NEXT: [[TERMINATED_BY_CUR1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds ptr, ptr [[TERMINATED_BY_CUR1]], i64 1 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]] +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap2: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable +// CHECK: cont3: +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR1]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP3]], inttoptr (i64 -1 to ptr) +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] +// CHECK: terminated_by.loop_cont: +// CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 +// CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND]] +// CHECK: terminated_by.loop_end: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// +int *__single *__terminated_by(-1) nested_indexable(int *__single *__indexable ptr) { + return __unsafe_terminated_by_from_indexable(-1, ptr); +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-ptr-relaxed-casting.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-ptr-relaxed-casting.c new file mode 100644 index 0000000000000..794db108a5ee2 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/terminated-by-ptr-relaxed-casting.c @@ -0,0 +1,109 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -Wno-error=bounds-safety-strict-terminated-by-cast -emit-llvm %s -o - | FileCheck %s + +#include + +// This should be removed by rdar://118390724 +// Until then this is here to make sure that Sema retains a valid AST when emitted as warning, so that CodeGen doesn't crash + +void foo(const char * __null_terminated); +void bar(const char * __null_terminated * __single); + +// CHECK-LABEL: define dso_local void @test +// CHECK-SAME: (ptr noundef [[SP:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SP_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[NTP:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[NTP2:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[NTP3:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[SPP:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[NTPP:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[NTPP2:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[NTPP3:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[SP]], ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: store ptr [[TMP0]], ptr [[NTP]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[NTP2]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[TMP2]]) +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[TMP3]]) +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[NTP]], align 8 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[NTP3]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[NTP3]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[SP_ADDR]], align 8 +// CHECK-NEXT: store ptr [[TMP6]], ptr [[NTP3]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr ptr, ptr [[SP_ADDR]], i64 1 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[SP_ADDR]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[SP_ADDR]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: unreachable +// CHECK: cont: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]] +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT2]], label [[TRAP1:%.*]] +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]] +// CHECK-NEXT: unreachable +// CHECK: cont2: +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[SPP]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[NTPP]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[NTPP2]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP16]]) +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP17]]) +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[NTPP]], align 8 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP19]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP20]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: ret void +// +void test(const char * __single sp) { + const char * __null_terminated ntp = sp; + const char * __null_terminated ntp2 = (const char * __null_terminated) sp; + + foo(sp); + foo((const char * __null_terminated) sp); + + const char * __null_terminated ntp3 = ntp; + ntp3 = sp; + ntp3 = (const char * __null_terminated) sp; + + + /* --- Nested --- */ + + const char * __single * __single spp = &sp; + const char * __null_terminated * __single ntpp = spp; + const char * __null_terminated * __single ntpp2 = (const char * __null_terminated * __single) spp; + + bar(spp); + bar((const char * __null_terminated * __single) spp); + + const char * __null_terminated * __single ntpp3 = ntpp; + ntpp3 = spp; + ntpp3 = (const char * __null_terminated * __single) spp; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns-O2.c new file mode 100644 index 0000000000000..4abbf4260350a --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns-O2.c @@ -0,0 +1,30 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 + +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -ftrap-function=fb_trap -ftrap-function-returns -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=X86_64 + +#include + +// X86_64-LABEL: define dso_local i32 @foo( +// X86_64-SAME: ptr noundef readonly captures(address) [[BAR:%.*]], i32 noundef [[COUNT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// X86_64-NEXT: entry: +// X86_64-NEXT: [[IDX_EXT:%.*]] = zext i32 [[COUNT]] to i64 +// X86_64-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[BAR]], i64 [[IDX_EXT]] +// X86_64-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[BAR]], i64 4 +// X86_64-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[ADD_PTR]], !annotation [[META2:![0-9]+]] +// X86_64-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// X86_64: trap: +// X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1:[0-9]+]], !annotation [[META2]] +// X86_64-NEXT: br label [[CONT]], !annotation [[META2]] +// X86_64: cont: +// X86_64-NEXT: [[DOTNOT:%.*]] = icmp ult ptr [[ARRAYIDX]], [[BAR]], !annotation [[META4:![0-9]+]] +// X86_64-NEXT: br i1 [[DOTNOT]], label [[TRAP1:%.*]], label [[CONT2:%.*]], !prof [[PROF5:![0-9]+]], !annotation [[META4]] +// X86_64: trap1: +// X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META4]] +// X86_64-NEXT: br label [[CONT2]], !annotation [[META4]] +// X86_64: cont2: +// X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA6:![0-9]+]] +// X86_64-NEXT: ret i32 [[TMP1]] +// +int foo(int *__counted_by(count) bar, unsigned count) { + return bar[1]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns.c new file mode 100644 index 0000000000000..ae614d4d98f97 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-function-returns.c @@ -0,0 +1,53 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 + +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -ftrap-function=fb_trap -ftrap-function-returns -emit-llvm %s -o - | FileCheck %s --check-prefix=X86_64 + +#include + +// X86_64-LABEL: define dso_local i32 @foo +// X86_64-SAME: (ptr noundef [[BAR:%.*]], i32 noundef [[COUNT:%.*]]) #[[ATTR0:[0-9]+]] { +// X86_64-NEXT: entry: +// X86_64-NEXT: [[BAR_ADDR:%.*]] = alloca ptr, align 8 +// X86_64-NEXT: [[COUNT_ADDR:%.*]] = alloca i32, align 4 +// X86_64-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// X86_64-NEXT: store ptr [[BAR]], ptr [[BAR_ADDR]], align 8 +// X86_64-NEXT: store i32 [[COUNT]], ptr [[COUNT_ADDR]], align 4 +// X86_64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BAR_ADDR]], align 8 +// X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[COUNT_ADDR]], align 4 +// X86_64-NEXT: [[IDX_EXT:%.*]] = zext i32 [[TMP1]] to i64 +// X86_64-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 [[IDX_EXT]] +// X86_64-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// X86_64-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// X86_64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// X86_64-NEXT: store ptr [[ADD_PTR]], ptr [[TMP3]], align 8 +// X86_64-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// X86_64-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// X86_64-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// X86_64-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// X86_64-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1 +// X86_64-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// X86_64-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// X86_64-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// X86_64-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// X86_64-NEXT: [[TMP6:%.*]] = icmp ult ptr [[TMP5]], [[WIDE_PTR_UB]], !annotation [[META2:![0-9]+]] +// X86_64-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// X86_64: trap: +// X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1:[0-9]+]], !annotation [[META2]] +// X86_64-NEXT: br label [[CONT]], !annotation [[META2]] +// X86_64: cont: +// X86_64-NEXT: [[TMP7:%.*]] = icmp uge ptr [[TMP5]], [[WIDE_PTR_LB]], !annotation [[META3:![0-9]+]] +// X86_64-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !annotation [[META3]] +// X86_64: trap1: +// X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META3]] +// X86_64-NEXT: br label [[CONT2]], !annotation [[META3]] +// X86_64: cont2: +// X86_64-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP5]], align 4 +// X86_64-NEXT: ret i32 [[TMP8]] +// +int foo(int *__counted_by(count) bar, unsigned count) { + return bar[1]; +} +//. +// X86_64: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// X86_64: [[META3]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c new file mode 100644 index 0000000000000..fab6e75649132 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c @@ -0,0 +1,40 @@ + +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_bidi.ll +// RUN: echo "; __SEPERATOR__" > %t.sep +// RUN: cat %t_bidi.ll %t.sep %t_bidi.ll > %t_bidi.repeated.ll +// RUN: FileCheck %s --input-file=%t_bidi.repeated.ll + +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_idx.ll +// RUN: echo "; __SEPERATOR__" > %t.sep +// RUN: cat %t_idx.ll %t.sep %t_idx.ll > %t_idx.repeated.ll +// RUN: FileCheck %s --input-file=%t_idx.repeated.ll + +#include + +#ifndef TYPE +#error TYPE must be defined +#endif + +typedef struct Data { + int a; + int b; +} Data_t; + +int* TYPE operation(Data_t* TYPE d) { + return &d->a; +} + +// In first copy of the file +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Pointer to struct above bounds while taking address of struct member", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) +// CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 24, column: 12, scope: {{![0-9]+}}) +// CHECK-LABEL: ; __SEPERATOR__ + +// In second copy of the file +// CHECK-LABEL: @operation +// Note: We use the `OPT_REMARK` to make sure we match against the correct branch. +// Unfortunately `SRC_LOC` is not enough because it isn't unique. +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c new file mode 100644 index 0000000000000..af2be0ad09712 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c @@ -0,0 +1,20 @@ + +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +#include + +int* __single operation(int* TYPE i) { + return i; +} + +// CHECK-LABEL: @operation +// We don't try to match the registers used in the comparison because trying +// to match the IR is very fragile. +// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] +// CHECK: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] +// CHECK: [[TRAP_LABEL]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] + +// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) +// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Pointer above bounds while casting", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{.+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[LOC]] = !DILocation(line: 7, column: 12, scope: {{![0-9]+}}) diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c new file mode 100644 index 0000000000000..9088cb3a42c54 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c @@ -0,0 +1,19 @@ + +// RUN: %clang_cc1 -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s + +int operation(int index) { + int array[] = {0, 1, 2}; + return array[index]; +} + +// CHECK-LABEL: @operation +// We don't try to match the registers used in the comparison because trying +// to match the IR is very fragile. +// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] +// CHECK-NEXT: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] +// CHECK: [[TRAP_LABEL]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] + +// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) +// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[LOC]] = !DILocation(line: 6, column: 10, scope: {{![0-9]+}}) diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c new file mode 100644 index 0000000000000..f296f55a5aa34 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c @@ -0,0 +1,24 @@ + +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +#include + +#ifndef TYPE +#error TYPE must be defined +#endif + +int operation(int* TYPE i) { + return *i; +} + +// CHECK-LABEL: @operation +// We don't try to match the registers used in the comparison because trying +// to match the IR is very fragile. +// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] +// CHECK-NEXT: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] +// CHECK: [[TRAP_LABEL]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] + +// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) +// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[LOC]] = !DILocation(line: 11, column: 12, scope: {{![0-9]+}}) diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c new file mode 100644 index 0000000000000..6f452255250c8 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c @@ -0,0 +1,105 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5 + +// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety \ +// RUN: -funique-traps -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefix=OPT0 %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety \ +// RUN: -funique-traps -emit-llvm %s -disable-llvm-passes -o - \ +// RUN: | FileCheck -check-prefix=OPT2 %s + +#include + +int consume(int* __bidi_indexable ptr, int idx) { + return ptr[idx]; +} +// OPT0-LABEL: define i32 @consume( +// OPT0-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) #[[ATTR0:[0-9]+]] { +// OPT0-NEXT: [[ENTRY:.*:]] +// OPT0-NEXT: [[PTR_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// OPT0-NEXT: [[IDX_ADDR:%.*]] = alloca i32, align 4 +// OPT0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// OPT0-NEXT: store ptr [[PTR]], ptr [[PTR_INDIRECT_ADDR]], align 8 +// OPT0-NEXT: store i32 [[IDX]], ptr [[IDX_ADDR]], align 4 +// OPT0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// OPT0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// OPT0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// OPT0-NEXT: [[TMP0:%.*]] = load i32, ptr [[IDX_ADDR]], align 4 +// OPT0-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// OPT0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// OPT0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// OPT0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// OPT0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// OPT0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// OPT0-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META2:![0-9]+]] +// OPT0-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// OPT0: [[TRAP]]: +// OPT0-NEXT: call void asm sideeffect "", "n"(i64 0), !annotation [[META2]] +// OPT0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] +// OPT0-NEXT: unreachable, !annotation [[META2]] +// OPT0: [[CONT]]: +// OPT0-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]] +// OPT0-NEXT: br i1 [[TMP2]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// OPT0: [[TRAP1]]: +// OPT0-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META4]] +// OPT0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] +// OPT0-NEXT: unreachable, !annotation [[META4]] +// OPT0: [[CONT2]]: +// OPT0-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// OPT0-NEXT: ret i32 [[TMP3]] +// +// +// OPT2-LABEL: define i32 @consume( +// OPT2-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) #[[ATTR0:[0-9]+]] { +// OPT2-NEXT: [[ENTRY:.*:]] +// OPT2-NEXT: [[PTR_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// OPT2-NEXT: [[IDX_ADDR:%.*]] = alloca i32, align 4 +// OPT2-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// OPT2-NEXT: store ptr [[PTR]], ptr [[PTR_INDIRECT_ADDR]], align 8, !tbaa [[TBAA2:![0-9]+]] +// OPT2-NEXT: store i32 [[IDX]], ptr [[IDX_ADDR]], align 4, !tbaa [[TBAA8:![0-9]+]] +// OPT2-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT10:![0-9]+]] +// OPT2-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// OPT2-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// OPT2-NEXT: [[TMP0:%.*]] = load i32, ptr [[IDX_ADDR]], align 4, !tbaa [[TBAA8]] +// OPT2-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// OPT2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// OPT2-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// OPT2-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// OPT2-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// OPT2-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// OPT2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META13:![0-9]+]] +// OPT2-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF14:![0-9]+]], !annotation [[META13]] +// OPT2: [[TRAP]]: +// OPT2-NEXT: call void asm sideeffect "", "n"(i64 0), !annotation [[META13]] +// OPT2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META13]] +// OPT2-NEXT: unreachable, !annotation [[META13]] +// OPT2: [[CONT]]: +// OPT2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META15:![0-9]+]] +// OPT2-NEXT: br i1 [[TMP2]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF14]], !annotation [[META15]] +// OPT2: [[TRAP1]]: +// OPT2-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META15]] +// OPT2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META15]] +// OPT2-NEXT: unreachable, !annotation [[META15]] +// OPT2: [[CONT2]]: +// OPT2-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA8]] +// OPT2-NEXT: ret i32 [[TMP3]] +// +//. +// OPT0: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// OPT0: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +// OPT0: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. +// OPT2: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0} +// OPT2: [[META3]] = !{!"p2 int", [[META4:![0-9]+]], i64 0} +// OPT2: [[META4]] = !{!"any p2 pointer", [[META5:![0-9]+]], i64 0} +// OPT2: [[META5]] = !{!"any pointer", [[META6:![0-9]+]], i64 0} +// OPT2: [[META6]] = !{!"omnipotent char", [[META7:![0-9]+]], i64 0} +// OPT2: [[META7]] = !{!"Simple C/C++ TBAA"} +// OPT2: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0} +// OPT2: [[META9]] = !{!"int", [[META6]], i64 0} +// OPT2: [[TBAA_STRUCT10]] = !{i64 0, i64 24, [[META11:![0-9]+]]} +// OPT2: [[META11]] = !{[[META12:![0-9]+]], [[META12]], i64 0} +// OPT2: [[META12]] = !{!"p1 int", [[META5]], i64 0} +// OPT2: [[META13]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// OPT2: [[PROF14]] = !{!"branch_weights", i32 1048575, i32 1} +// OPT2: [[META15]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +//. diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign-O2.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign-O2.c new file mode 100644 index 0000000000000..fe937a5e5dc76 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign-O2.c @@ -0,0 +1,136 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple arm64 %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64 %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @wide_array_subscript_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void wide_array_subscript_ok() { + int *__indexable arr[5]; + int *__indexable *__indexable buf = arr; + buf[4] = 0; +} + +// CHECK-LABEL: @wide_array_subscript_trap1( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void wide_array_subscript_trap1() { + int *__indexable arr[5]; + int *__indexable *__indexable buf = arr; + buf[5] = 0; +} + +// CHECK-LABEL: @wide_array_subscript_trap2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [5 x %"__bounds_safety::wide_ptr.indexable"], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 80, ptr nonnull [[ARR]]) #[[ATTR6:[0-9]+]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 80 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 -16 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont1: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 80, ptr nonnull [[ARR]]) #[[ATTR6]] +// CHECK-NEXT: ret void +// +void wide_array_subscript_trap2() { + int *__indexable arr[5]; + int *__indexable *buf = arr; + buf[-1] = 0; +} + +// CHECK-LABEL: @wide_array_subscript_read_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void wide_array_subscript_read_ok() { + int *__indexable arr[5]; + int *__indexable *__indexable buf = arr; + (void)buf[4]; +} + +// CHECK-LABEL: @wide_array_subscript_read_ok2( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void wide_array_subscript_read_ok2() { + int *__indexable arr[5]; + int *__indexable *__indexable buf = arr; + (void)&buf[5]; +} + +// CHECK-LABEL: @wide_array_subscript_read_trap( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void wide_array_subscript_read_trap() { + int *__indexable arr[5]; + int *__indexable *__indexable buf = arr; + (void)buf[5]; +} + +// CHECK-LABEL: @wide_deref_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void wide_deref_ok() { + int *__indexable arr[5]; + int *__indexable *buf = arr; + *(buf + 4) = 0; +} + +// CHECK-LABEL: @wide_deref_trap( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// +void wide_deref_trap() { + int *__indexable arr[5]; + int *__indexable *buf = arr; + *(buf + 5) = 0; +} + +struct wide_member_t { + int *__bidi_indexable ptr; +}; +// CHECK-LABEL: @wide_member_assign_ok( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +void wide_member_assign_ok() { + struct wide_member_t w; + struct wide_member_t *wp = &w; + wp->ptr = 0; +} + +// CHECK-LABEL: @wide_member_assign_trap( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[W:%.*]] = alloca [[STRUCT_WIDE_MEMBER_T:%.*]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[W]]) #[[ATTR6]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[W]], i64 24 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[W]], i64 48 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP1]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont1: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[W]]) #[[ATTR6]] +// CHECK-NEXT: ret void +// +void wide_member_assign_trap() { + struct wide_member_t w; + struct wide_member_t *wp = &w + 1; + wp->ptr = 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign.c new file mode 100644 index 0000000000000..11d39a23dbf65 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-assign.c @@ -0,0 +1,236 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -O0 -fbounds-safety -emit-llvm -triple arm64 %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64 %s -o - | FileCheck %s + +#include + +// CHECK-LABEL: @wide_array_subscript( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: store [2 x i64] [[BUF_COERCE:%.*]], ptr [[BUF]], align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[BUF]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP3]] to i64 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[TMP4]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap6: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont7: +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 16, i1 false) +// CHECK-NEXT: ret void +// +void wide_array_subscript(int *__indexable *__indexable buf, int i) { + buf[i] = 0; +} + +// CHECK-LABEL: @wide_array_subscript_load( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: store [2 x i64] [[BUF_COERCE:%.*]], ptr [[BUF]], align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[BUF]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP3]] to i64 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[TMP4]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap6: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont7: +// CHECK-NEXT: ret void +// +void wide_array_subscript_load(int *__indexable *__indexable buf, int i) { + (void)buf[i]; +} + +// CHECK-LABEL: @wide_array_subscript_addr( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: store [2 x i64] [[BUF_COERCE:%.*]], ptr [[BUF]], align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BUF]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[TMP5]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP_ENSURED]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: ret void +// +void wide_array_subscript_addr(int *__indexable *__indexable buf, int i) { + (void)&buf[i]; +} + +// CHECK-LABEL: @wide_deref( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.indexable", align 8 +// CHECK-NEXT: store [2 x i64] [[BUF_COERCE:%.*]], ptr [[BUF]], align 8 +// CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[BUF]], i64 16, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[TMP5]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap6: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont7: +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[WIDE_PTR_PTR3]], i8 0, i64 16, i1 false) +// CHECK-NEXT: ret void +// +void wide_deref(int *__indexable *__indexable buf, int i) { + *(buf + i) = 0; +} + +struct wide_member_t { + int *__bidi_indexable ptr; +}; +// CHECK-LABEL: @wide_member_assign( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[W_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: store ptr [[W:%.*]], ptr [[W_INDIRECT_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[W]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_WIDE_MEMBER_T:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_WIDE_MEMBER_T]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 24, i1 false) +// CHECK-NEXT: ret void +// +void wide_member_assign(struct wide_member_t *__bidi_indexable w) { + w->ptr = 0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-addrof-deref.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-addrof-deref.c new file mode 100644 index 0000000000000..32aa2efd8fec9 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-addrof-deref.c @@ -0,0 +1,105 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 + +// CHECK-O0-LABEL: @foo( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP6]] +// +// CHECK-O2-LABEL: @foo( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int foo() { + int arr[10]; + int *ptr = arr; + int *ptr2 = &*ptr; + return ptr2[10]; +} + +// CHECK-O0-LABEL: @bar( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP6]] +// +// CHECK-O2-LABEL: @bar( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 undef +// +int bar() { + int arr[10]; + int *ptr = arr; + int *ptr2 = &*ptr; + return ptr2[9]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-deref-addrof.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-deref-addrof.c new file mode 100644 index 0000000000000..e1cf0a79792ad --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/wide-ptr-bound-deref-addrof.c @@ -0,0 +1,160 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" + +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +// RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 +// RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 +#include + +// +// We could have skipped '*&' entirely but this is fine too. +// CHECK-O0-LABEL: @foo( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i64 1 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[PTR]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap10: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont11: +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap12: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont13: +// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @foo( +// CHECK-O2-NEXT: trap: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable +// +int foo() { + int arr[10]; + int *__bidi_indexable ptr = arr; + int *ptr2 = *&ptr; + return ptr2[10]; +} + +// CHECK-O0-LABEL: @bar( +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i64 1 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[PTR]], ptr [[TMP4]], align 8 +// CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-O0-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[PTR]], ptr [[TMP6]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont2: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap10: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont11: +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0: trap12: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable +// CHECK-O0: cont13: +// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP12]] +// +// CHECK-O2-LABEL: @bar( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 undef +// +int bar() { + int arr[10]; + int *__bidi_indexable ptr = arr; + int *ptr2 = *&ptr; + return ptr2[9]; +} diff --git a/clang/test/BoundsSafety-legacy-checks/CodeGen/zero-length-pointers.c b/clang/test/BoundsSafety-legacy-checks/CodeGen/zero-length-pointers.c new file mode 100644 index 0000000000000..b35b1d12cf7a9 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/CodeGen/zero-length-pointers.c @@ -0,0 +1,1298 @@ +// REQUIRES: system-darwin +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ + +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - -O2 | FileCheck %s --check-prefix CHECK-O2 +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - -O2 | FileCheck %s --check-prefix CHECK-O2 + +#include +typedef __SIZE_TYPE__ size_t; + + +void counted_by(int *__counted_by(len) p, size_t len); +// CHECK-LABEL: @test_counted_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP37:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP53:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP62:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP76:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP3]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP4]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB30]], ptr [[TMP5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR32:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB34:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB36:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR35]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP37]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP37]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP37]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP37]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR32]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP44:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[CMP44]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP45]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 +// CHECK-NEXT: call void @counted_by(ptr noundef [[WIDE_PTR_PTR47]], i64 noundef 0) +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP12]], i64 1 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP19]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP53]], ptr align 8 [[AGG_TEMP52]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB55]], ptr [[TMP20]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR57:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR56]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB59:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR58]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB61:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR60]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP62]], ptr align 8 [[AGG_TEMP52]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR64:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR63]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB66:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR65]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST69:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR57]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST70:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR64]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB71:%.*]] = sub i64 [[SUB_PTR_LHS_CAST69]], [[SUB_PTR_RHS_CAST70]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV72:%.*]] = sdiv exact i64 [[SUB_PTR_SUB71]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP73:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV72]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP73]], label [[CONT75:%.*]], label [[TRAP74:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap74: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont75: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP76]], ptr align 8 [[AGG_TEMP52]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR78:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR77]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR79:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB80:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR79]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR81:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB82:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR81]], align 8 +// CHECK-NEXT: call void @counted_by(ptr noundef [[WIDE_PTR_PTR78]], i64 noundef 0) +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_counted_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4:[0-9]+]] +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @counted_by(ptr noundef nonnull [[ZERO]], i64 noundef 0) #[[ATTR4]] +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 +// CHECK-O2-NEXT: call void @counted_by(ptr noundef nonnull [[TMP0]], i64 noundef 0) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: ret void +// +void test_counted_by(void) { + int zero[0]; + int one; + counted_by(zero, 0); + counted_by(&one + 1, 0); +} + +void sized_by(void *__sized_by(len) p, size_t len); +// CHECK-LABEL: @test_sized_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP18:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP73:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP74:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP81:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP82:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP97:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP98:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP117:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR4:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR3]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB6:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB8:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP9]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB11]], ptr [[TMP6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR4]], [[WIDE_PTR_PTR13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB20]], ptr [[TMP7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP34:%.*]] = icmp ule ptr [[WIDE_PTR_PTR22]], [[WIDE_PTR_PTR29]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP34]], label [[LAND_RHS:%.*]], label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP11]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP35]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP51]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP65:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[CMP65]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP66]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR68:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR67]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB70:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR69]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP66]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB72:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR71]], align 8 +// CHECK-NEXT: call void @sized_by(ptr noundef [[WIDE_PTR_PTR68]], i64 noundef 0) +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP21]], i64 1 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP24]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP27:%.*]] = load ptr, ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR75:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR76:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR75]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB78:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR77]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR79:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP74]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB80:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR79]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP73]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR76]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP73]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB78]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP73]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB80]], ptr [[TMP31]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP82]], ptr align 8 [[AGG_TEMP73]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB84:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR83]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB84]], ptr [[TMP32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR86:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR85]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB88:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR87]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB90:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR89]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR86]], ptr [[TMP33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB88]], ptr [[TMP34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB90]], ptr [[TMP35]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR91:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR92:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR91]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR93:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB94:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR93]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR95:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP81]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB96:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR95]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP98]], ptr align 8 [[AGG_TEMP73]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR99:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP98]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR100:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR99]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR101:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP98]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB102:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR101]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR103:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP98]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB104:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR103]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR100]], ptr [[TMP36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB102]], ptr [[TMP37]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB104]], ptr [[TMP38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR105:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR106:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR105]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR107:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB108:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR107]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR109:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP97]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB110:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR109]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST111:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR92]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST112:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR106]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB113:%.*]] = sub i64 [[SUB_PTR_LHS_CAST111]], [[SUB_PTR_RHS_CAST112]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP114:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB113]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP114]], label [[CONT116:%.*]], label [[TRAP115:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap115: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont116: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP117]], ptr align 8 [[AGG_TEMP73]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR118:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP117]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR119:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR118]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR120:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP117]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB121:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR120]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR122:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP117]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB123:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR122]], align 8 +// CHECK-NEXT: call void @sized_by(ptr noundef [[WIDE_PTR_PTR119]], i64 noundef 0) +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_sized_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @sized_by(ptr noundef nonnull [[ZERO]], i64 noundef 0) #[[ATTR4]] +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 +// CHECK-O2-NEXT: call void @sized_by(ptr noundef nonnull [[TMP0]], i64 noundef 0) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: ret void +// +void test_sized_by(void) { + int zero[0]; + int one; + sized_by(zero, 0); + sized_by(&one + 1, 0); +} + +void ended_by(void *__ended_by(end) start, void *end); +// CHECK-LABEL: @test_ended_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP65:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP67:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP75:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP82:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP92:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP99:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[ARRAYDECAY4:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER5:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY4]], i64 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY4]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR7]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB9]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB11]], ptr [[TMP11]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR14:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP12]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB18:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB21]], ptr [[TMP12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR23:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR14]], [[WIDE_PTR_PTR23]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR37:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB39:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP42:%.*]] = icmp ule ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_PTR37]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: land.end: +// CHECK-NEXT: [[TMP13:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP42]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP43]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR45:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR44]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB47:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR46]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB49:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR48]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 +// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR45]], ptr noundef [[WIDE_PTR_PTR52]]) +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP19]], i64 1 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP22]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB62]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB64]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP33]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 0 +// CHECK-NEXT: [[TMP35:%.*]] = load ptr, ptr [[TMP34]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH68:%.*]] = getelementptr i32, ptr [[TMP35]], i64 1 +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH68]], ptr [[TMP36]], align 8 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 1 +// CHECK-NEXT: [[TMP38:%.*]] = load ptr, ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP38]], ptr [[TMP39]], align 8 +// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 2 +// CHECK-NEXT: [[TMP41:%.*]] = load ptr, ptr [[TMP40]], align 8 +// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP41]], ptr [[TMP42]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR70:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR69]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB72:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR71]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 +// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[TMP43]], align 8 +// CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB72]], ptr [[TMP44]], align 8 +// CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB74]], ptr [[TMP45]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP75]], ptr align 8 [[AGG_TEMP57]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR77:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR76]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB79:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR78]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB81:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR80]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP82]], ptr align 8 [[AGG_TEMP65]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR84:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR83]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB86:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR85]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB88:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR87]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP89:%.*]] = icmp ule ptr [[WIDE_PTR_PTR77]], [[WIDE_PTR_PTR84]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP89]], label [[CONT91:%.*]], label [[TRAP90:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap90: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont91: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP92]], ptr align 8 [[AGG_TEMP57]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR93:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR94:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR93]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR95:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB96:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR95]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR97:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB98:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR97]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP99]], ptr align 8 [[AGG_TEMP65]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR101:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR100]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB103:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR102]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR104:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB105:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR104]], align 8 +// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR94]], ptr noundef [[WIDE_PTR_PTR101]]) +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_ended_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @ended_by(ptr noundef nonnull [[ZERO]], ptr noundef nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 +// CHECK-O2-NEXT: call void @ended_by(ptr noundef nonnull [[BOUND_PTR_ARITH]], ptr noundef nonnull [[BOUND_PTR_ARITH]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: ret void +// +void test_ended_by(void) { + int zero[0]; + int one; + ended_by(zero, zero); + ended_by(&one + 1, &one + 1); +} + +void ended_by_itself(void *__ended_by(end) end); +// CHECK-LABEL: @test_ended_by_itself( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP18:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP25:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR4:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR3]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB6:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB8:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP9]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB11]], ptr [[TMP6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR4]], [[WIDE_PTR_PTR13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8 +// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR20]]) +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP12]], i64 1 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR28]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB30]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB32]], ptr [[TMP22]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR44:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB46:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR45]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB48:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP49:%.*]] = icmp ule ptr [[WIDE_PTR_PTR35]], [[WIDE_PTR_PTR44]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP49]], label [[CONT51:%.*]], label [[TRAP50:%.*]], {{!annotation ![0-9]+}} +// CHECK: trap50: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont51: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8 +// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR54]]) +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_ended_by_itself( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @ended_by_itself(ptr noundef nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 +// CHECK-O2-NEXT: call void @ended_by_itself(ptr noundef nonnull [[TMP0]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] +// CHECK-O2-NEXT: ret void +// +void test_ended_by_itself(void) { + int zero[0]; + int one; + ended_by_itself(zero); + ended_by_itself(&one + 1); +} + +struct counted_by { + int *__counted_by(len) p; + size_t len; +}; + +// CHECK-LABEL: @test_struct_counted_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_COUNTED_BY:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[STRUCT_COUNTED_BY]], align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[P]], align 8 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN]], align 8 +// CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP8]], i64 1 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR5]], ptr [[P2]], align 8 +// CHECK-NEXT: [[LEN10:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED1]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN10]], align 8 +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_struct_counted_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret void +// +void test_struct_counted_by(void) { + int zero[0]; + int one; + (void) (struct counted_by) {zero, 0}; + (void) (struct counted_by) {&one + 1, 0}; +} + +struct sized_by { + void *__sized_by(len) p; + size_t len; +}; + +// CHECK-LABEL: @test_struct_sized_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_SIZED_BY:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED8:%.*]] = alloca [[STRUCT_SIZED_BY]], align 8 +// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[P]], align 8 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN]], align 8 +// CHECK-NEXT: [[P9:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP11]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[P9]], align 8 +// CHECK-NEXT: [[LEN24:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN24]], align 8 +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_struct_sized_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret void +// +void test_struct_sized_by(void) { + int zero[0]; + int one; + (void) (struct sized_by) {zero, 0}; + (void) (struct sized_by) {&one + 1, 0}; +} + +struct ended_by { + void *__ended_by(end) start; + void *end; +}; + +// CHECK-LABEL: @test_struct_ended_by( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_ENDED_BY:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED24:%.*]] = alloca [[STRUCT_ENDED_BY]], align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[START:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[START]], align 8 +// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY10:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER11:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY10]], i64 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY10]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER11]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY10]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[END]], align 8 +// CHECK-NEXT: [[START25:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED24]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP12]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP17]], i64 1 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP20]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR29]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB31]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB33]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR35]], ptr [[START25]], align 8 +// CHECK-NEXT: [[END40:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED24]], i32 0, i32 1 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP28]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 0 +// CHECK-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP32]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH44:%.*]] = getelementptr i32, ptr [[TMP33]], i64 1 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH44]], ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 1 +// CHECK-NEXT: [[TMP36:%.*]] = load ptr, ptr [[TMP35]], align 8 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP36]], ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 2 +// CHECK-NEXT: [[TMP39:%.*]] = load ptr, ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP39]], ptr [[TMP40]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 +// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR46]], ptr [[TMP41]], align 8 +// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB48]], ptr [[TMP42]], align 8 +// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB50]], ptr [[TMP43]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR52]], ptr [[END40]], align 8 +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_struct_ended_by( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret void +// +void test_struct_ended_by(void) { + int zero[0]; + int one; + (void) (struct ended_by) {zero, zero}; + (void) (struct ended_by) {&one + 1, &one + 1}; +} + +struct ended_by_itself { + void *__ended_by(end) end; +}; + +// CHECK-LABEL: @test_struct_ended_by_itself( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 +// CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_ENDED_BY_ITSELF:%.*]], align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED8:%.*]] = alloca [[STRUCT_ENDED_BY_ITSELF]], align 8 +// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[END]], align 8 +// CHECK-NEXT: [[END9:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP11]], i64 1 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[END9]], align 8 +// CHECK-NEXT: ret void +// +// CHECK-O2-LABEL: @test_struct_ended_by_itself( +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret void +// +void test_struct_ended_by_itself(void) { + int zero[0]; + int one; + (void) (struct ended_by_itself) {zero}; + (void) (struct ended_by_itself) {&one + 1}; +} diff --git a/clang/test/BoundsSafety-legacy-checks/Profile/flexible-array-member-checks-code-coverage.c b/clang/test/BoundsSafety-legacy-checks/Profile/flexible-array-member-checks-code-coverage.c new file mode 100644 index 0000000000000..2f13fef9e416f --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Profile/flexible-array-member-checks-code-coverage.c @@ -0,0 +1,53 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 3 + + +// RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -fprofile-instrument=clang -fcoverage-mapping -emit-llvm %s -o - | FileCheck %s + +#include + +struct s { + int count; + int fam[__counted_by(count)]; +}; + +void bar(struct s *p); + +// CHECK-LABEL: define dso_local void @foo( +// CHECK-SAME: ptr noundef [[BUF:%.*]], i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PGOCOUNT:%.*]] = load i64, ptr @__profc_foo, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PGOCOUNT]], 1 +// CHECK-NEXT: store i64 [[TMP0]], ptr @__profc_foo, align 8 +// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[SIZE]] to i64 +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[BUF]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label [[CONT40:%.*]], label [[FLEX_BASE_NONNULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[BUF]], i64 4 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[BUF]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[DOTNOT49:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT49]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT27:%.*]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont27: +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[BUF]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sgt i32 [[TMP2]], -1, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT30:%.*]], label [[TRAP]], !prof [[PROF13:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: cont30: +// CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[IDX_EXT]], -4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[GEPDIFF]], 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[TMP2]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp ult i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[DOTNOT50:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND52:%.*]] = or i1 [[DOTNOT50]], [[FLEX_COUNT_CHECK_NOT]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND52]], label [[TRAP]], label [[CONT40]], !prof [[PROF17:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: cont40: +// CHECK-NEXT: tail call void @bar(ptr noundef [[BUF]]) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: ret void +// +void foo(void *__sized_by(size) buf, unsigned size) { + struct s *p = (struct s *)buf; + bar(p); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/bounds-checks-inline.c b/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/bounds-checks-inline.c new file mode 100644 index 0000000000000..718e1d18cf766 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/bounds-checks-inline.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fbounds-safety %s -I %S/include -verify=legacy,legacy-incorrect,common-incorrect,common +// RUN: %clang_cc1 -fbounds-safety %s -I %S/include -verify=strict,common -fno-bounds-safety-relaxed-system-headers +// RUN: %clang_cc1 -fbounds-safety -fbounds-safety-bringup-missing-checks=all %s -DTEST_COMPOUND_LITERALS -I %S/include -verify=incorrect,common-incorrect,common +// RUN: %clang_cc1 -fbounds-safety -fbounds-safety-bringup-missing-checks=all %s -DTEST_COMPOUND_LITERALS -I %S/include -verify=strict,common -fno-bounds-safety-relaxed-system-headers +#include diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/include/bounds-checks-inline.h b/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/include/bounds-checks-inline.h new file mode 100644 index 0000000000000..8bfe1138a9aa1 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/SystemHeaders/include/bounds-checks-inline.h @@ -0,0 +1,162 @@ +// Pretend this is a system header +#pragma clang system_header +#include + +int* get_unspecified_ptr(void); +int* __unsafe_indexable get_unsafe_ptr(void); +// strict-note@+1 2{{passing argument to parameter 'ptr' here}} +void receive_cb(int* __counted_by(count) ptr, int count); + +// TODO: The `incorrect-error`s and `common-incorrect-error`s should not be emitted. +// They are a result of a bug +// and we emit the diagnostic rather than crashing (rdar://139815437). + +// FIXME: The `FIXME-common-incorrect-error`` should be emitted but aren't for +// some reason (rdar://140145190). + +inline int* __counted_by(count) inline_header_func_get_unspecified_ptr(int count) { + // Outside of system headers this implicit conversion is not + // allowed but it's allowed in system headers. + // strict-error@+2{{returning 'int *' from a function with incompatible result type 'int *__single __counted_by(count)' (aka 'int *__single') casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // incorrect-error@+1{{cannot extract the lower bound of 'int *' because it has no bounds specification}} + return get_unspecified_ptr(); +} + +inline int* __counted_by(count) inline_header_func_get_unsafe_ptr(int count) { + // Outside of system headers this implicit conversion is not + // allowed but it's allowed in system headers. + // strict-error@+2{{returning 'int *__unsafe_indexable' from a function with incompatible result type 'int *__single __counted_by(count)' (aka 'int *__single') casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // incorrect-error@+1{{cannot extract the lower bound of 'int *__unsafe_indexable' because it has no bounds specification}} + return get_unsafe_ptr(); +} + +inline int* __counted_by(count) inline_header_ret_explicit_unspecified_cast_0(int count) { + // Outside of system headers this implicit conversion **is allowed** + return (int*)0; +} + + +inline int* __counted_by(count) inline_header_ret_explicit_unsafe_indexable_cast_0(int count) { + // Outside of system headers this implicit conversion is not + // allowed but it's allowed in system headers. + return (int* __unsafe_indexable)0; +} + +inline int* __counted_by(count) inline_header_ret_0(int count) { + // Outside of system headers this implicit conversion **is allowed** + return 0; +} + +inline int* __counted_by(count) inline_header_ret_void_star_unspecified_0(int count) { + // Outside of system headers this implicit conversion **is allowed** + return (void*)0; +} + +inline int* __counted_by(count) inline_header_ret_void_star_unsafe_indexable_0(int count) { + // Outside of system headers this implicit conversion is not + // allowed but it's allowed in system headers. + return (void* __unsafe_indexable) 0; +} + +inline void inline_header_call_receive_cb_cast_0(void) { + receive_cb((int*)0, 0); +} + +inline void inline_header_call_receive_cb_cast_unspecified_ptr(void) { + // strict-error@+1{{passing 'int *' to parameter of incompatible type 'int *__single __counted_by(count)' (aka 'int *__single') casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + receive_cb(get_unspecified_ptr(), 0); +} + +inline void inline_header_call_receive_cb_cast_unsafe_ptr(void) { + // strict-error@+1{{passing 'int *__unsafe_indexable' to parameter of incompatible type 'int *__single __counted_by(count)' (aka 'int *__single') casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + receive_cb(get_unsafe_ptr(), 0); +} + +inline void inline_header_assign_local_cb_cast_0(void) { + int count = 0; + int* __counted_by(count) local = (int*)0; + + local = (int*)0; + count = 0; +} + + +void side_effect(void); + + +inline void inline_header_init_local_cb_unspecified_ptr(void) { + // common-error@+1{{local variable count must be declared right next to its dependent decl}} + int count = 0; + // strict-error@+3{{initializing 'int *__single __counted_by(count)' (aka 'int *__single') with an expression of incompatible type 'int *' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // common-error@+2{{local variable local must be declared right next to its dependent decl}} + // common-incorrect-error@+1{{cannot extract the lower bound of 'int *' because it has no bounds specification}} + int* __counted_by(count) local = get_unspecified_ptr(); +} + +inline void inline_header_assign_local_cb_unspecified_ptr(void) { + int count2 = 0; + int* __counted_by(count2) local2; + + side_effect(); + + // strict-error@+3{{assigning to 'int *__single __counted_by(count2)' (aka 'int *__single') from incompatible type 'int *' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // FIXME: The errors in the previous function stop this error from appearing for some reason. + // FIXME-common-incorrect-error@+1{{cannot extract the lower bound of 'int *' because it has no bounds specification}} + local2 = get_unspecified_ptr(); + // strict-error@+1{{assignment to 'count2' requires corresponding assignment to 'int *__single __counted_by(count2)' (aka 'int *__single') 'local2'; add self assignment 'local2 = local2' if the value has not changed}} + count2 = 0; +} + +inline void inline_header_init_local_cb_unsafe_ptr(void) { + // common-error@+1{{local variable count must be declared right next to its dependent decl}} + int count = 0; + // strict-error@+3{{initializing 'int *__single __counted_by(count)' (aka 'int *__single') with an expression of incompatible type 'int *__unsafe_indexable' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // common-error@+2{{local variable local must be declared right next to its dependent decl}} + // common-incorrect-error@+1{{cannot extract the lower bound of 'int *__unsafe_indexable' because it has no bounds specification}} + int* __counted_by(count) local = get_unsafe_ptr(); +} + +inline void inline_header_assign_local_cb_unsafe_ptr(void) { + int count2 = 0; + int* __counted_by(count2) local2; + + side_effect(); + + // strict-error@+3{{assigning to 'int *__single __counted_by(count2)' (aka 'int *__single') from incompatible type 'int *__unsafe_indexable' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // FIXME: The errors in the previous functions stop this error from appearing for some reason. + // FIXME-common-incorrect-error@+1{{cannot extract the lower bound of 'int *' because it has no bounds specification}} + local2 = get_unsafe_ptr(); + // strict-error@+1{{assignment to 'count2' requires corresponding assignment to 'int *__single __counted_by(count2)' (aka 'int *__single') 'local2'; add self assignment 'local2 = local2' if the value has not changed}} + count2 = 0; +} + +#ifdef TEST_COMPOUND_LITERALS + +struct simple_cb { + int count; + int* __counted_by(count) ptr; +}; + + +inline void inline_header_compound_literal_unspecified_ptr(struct simple_cb s, int* unspecified_ptr) { + // FIXME: This diagnostic isn't emitted when there are diagnostics from other functions. + // strict-error@+2{{initializing 'int *__single __counted_by(count)' (aka 'int *__single') with an expression of incompatible type 'int *' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // fixme-incorrect-error@+1{{cannot extract the lower bound of 'int *' because it has no bounds specification}} + s = (struct simple_cb){.count = 0, .ptr = unspecified_ptr}; +} + +inline void inline_header_compound_literal_unspecified_cast_0(struct simple_cb s) { + s = (struct simple_cb){.count = 0, .ptr = (int*)0}; +} + +inline void inline_header_compound_literal_unsafe_indexable_cast_0(struct simple_cb s) { + s = (struct simple_cb){.count = 0, .ptr = (int* __unsafe_indexable)0}; +} + +inline void inline_header_compound_literal_unsafe_indexable_ptr(struct simple_cb s, int* __unsafe_indexable unsafe_indexable_ptr) { + // strict-error@+2{{initializing 'int *__single __counted_by(count)' (aka 'int *__single') with an expression of incompatible type 'int *__unsafe_indexable' casts away '__unsafe_indexable' qualifier; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable' to perform this conversion}} + // incorrect-error@+1{{cannot extract the lower bound of 'int *__unsafe_indexable' because it has no bounds specification}} + s = (struct simple_cb){.count = 0, .ptr = unsafe_indexable_ptr}; +} + +#endif diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/bounds-attributed-in-return-immutable-dependent-param.c b/clang/test/BoundsSafety-legacy-checks/Sema/bounds-attributed-in-return-immutable-dependent-param.c new file mode 100644 index 0000000000000..5bec5530cdd98 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/bounds-attributed-in-return-immutable-dependent-param.c @@ -0,0 +1,143 @@ + + +// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,legacy %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s + +#include + +void i(int); +void pi(int *); +void ppi(int **); +void pppi(int ***); + +// __counted_by() + +void cb_in_in(int count, int *__counted_by(count) ptr); +void cb_in_out(int count, int *__counted_by(count) *ptr); +void cb_out_in(int *count, int *__counted_by(*count) ptr); +void cb_out_out(int *count, int *__counted_by(*count) *ptr); + +int *__counted_by(count) ret_cb_in(int count); +int *__counted_by(*count) ret_cb_out(int *count); + +int *__counted_by(count) mixed_simple(int count, int *__counted_by(count) ptr); +int *__counted_by(*count) mixed_inout_count(int *count, int *__counted_by(*count) ptr); +int *__counted_by(*count) mixed_out_ptr(int *count, int *__counted_by(*count) *ptr); +int *__counted_by(*count) mixed_inout_count_out_ptr(int *count, int *__counted_by(*count) ptr, int *__counted_by(*count) *out_ptr); + +int *__counted_by(count) test_cb_in(int count) { + int c; + int *__counted_by(c) p; + + count = 42; // rs-error{{parameter 'count' is implicitly read-only due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + + i(count); + pi(&count); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + + cb_in_in(count, p); + cb_in_out(count, &p); // expected-error{{passing address of 'p' as an indirect parameter; must also pass 'c' or its address because the type of 'p', 'int *__single __counted_by(c)' (aka 'int *__single'), refers to 'c'}} + cb_out_in(&count, p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + cb_out_out(&count, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + + (void)ret_cb_in(count); + (void)ret_cb_out(&count); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + + (void)mixed_simple(count, p); + (void)mixed_inout_count(&count, p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + (void)mixed_out_ptr(&count, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + (void)mixed_inout_count_out_ptr(&count, p, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_in' ('int *__single __counted_by(count)' (aka 'int *__single'))}} +} + +int *__counted_by(*count) test_cb_out(int *count) { + int c; + int *__counted_by(c) p; + + *count = 42; + count = p; // expected-error{{not allowed to change out parameter used as dependent count expression of other parameter or return type}} + + i(*count); + pi(count); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_out' ('int *__single __counted_by(*count)' (aka 'int *__single'))}} + ppi(&count); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_out' ('int *__single __counted_by(*count)' (aka 'int *__single'))}} + + cb_in_in(*count, p); + cb_in_out(*count, &p); // expected-error{{passing address of 'p' as an indirect parameter; must also pass 'c' or its address because the type of 'p', 'int *__single __counted_by(c)' (aka 'int *__single'), refers to 'c'}} + cb_out_in(count, p); + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + cb_out_out(count, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_out' ('int *__single __counted_by(*count)' (aka 'int *__single'))}} + + (void)ret_cb_in(*count); + (void)ret_cb_out(count); + + (void)mixed_simple(*count, p); + (void)mixed_inout_count(count, p); + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + (void)mixed_out_ptr(count, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_out' ('int *__single __counted_by(*count)' (aka 'int *__single'))}} + // legacy-error@+1{{incompatible dynamic count pointer argument to parameter of type 'int *__single'}} + (void)mixed_inout_count_out_ptr(count, p, &p); // rs-error{{parameter 'count' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__counted_by' attribute in the return type of 'test_cb_out' ('int *__single __counted_by(*count)' (aka 'int *__single'))}} +} + +// Other variants of __counted_by() +// The logic is the same as for __counted_by(), so test only a few cases. + +int *__counted_by_or_null(count) test_cbn_in(int count) { + count = 42; // rs-error{{parameter 'count' is implicitly read-only due to being used by the '__counted_by_or_null' attribute in the return type of 'test_cbn_in' ('int *__single __counted_by_or_null(count)' (aka 'int *__single'))}} +} + +void *__sized_by(size) test_sb_in(int size) { + size = 42; // rs-error{{parameter 'size' is implicitly read-only due to being used by the '__sized_by' attribute in the return type of 'test_sb_in' ('void *__single __sized_by(size)' (aka 'void *__single'))}} +} + +void *__sized_by_or_null(size) test_sbn_in(int size) { + size = 42; // rs-error{{parameter 'size' is implicitly read-only due to being used by the '__sized_by_or_null' attribute in the return type of 'test_sbn_in' ('void *__single __sized_by_or_null(size)' (aka 'void *__single'))}} +} + +// __ended_by() + +void eb_in(int *__ended_by(end) start, int *end); +void eb_out(int *__ended_by(*end) start, int **end); + +int *__ended_by(end) ret_eb_in(int *end); +int *__ended_by(*end) ret_eb_out(int **end); + +int *__ended_by(end) test_eb_in(int *end) { + int *p; + + *end = 42; + end = p; // rs-error{{parameter 'end' is implicitly read-only due to being used by the '__ended_by' attribute in the return type of 'test_eb_in' ('int *__single __ended_by(end)' (aka 'int *__single'))}} + + i(*end); + pi(end); + ppi(&end); // rs-error{{parameter 'end' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__ended_by' attribute in the return type of 'test_eb_in' ('int *__single __ended_by(end)' (aka 'int *__single'))}} + + eb_in(p, end); + eb_out(p, &end); // expected-error{{type of 'end', 'int *__single', is incompatible with parameter of type 'int *__single /* __started_by(start) */ ' (aka 'int *__single')}} + + (void)ret_eb_in(end); + (void)ret_eb_out(&end); // rs-error{{parameter 'end' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__ended_by' attribute in the return type of 'test_eb_in' ('int *__single __ended_by(end)' (aka 'int *__single'))}} +} + +int *__ended_by(*end) test_eb_out(int **end) { + int *__single p; + + **end = 42; + *end = p; + end = &p; // rs-error{{parameter 'end' is implicitly read-only due to being used by the '__ended_by' attribute in the return type of 'test_eb_out' ('int *__single __ended_by(*end)' (aka 'int *__single'))}} + + i(**end); + pi(*end); + ppi(end); // rs-error{{parameter 'end' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__ended_by' attribute in the return type of 'test_eb_out' ('int *__single __ended_by(*end)' (aka 'int *__single'))}} + pppi(&end); // rs-error{{parameter 'end' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__ended_by' attribute in the return type of 'test_eb_out' ('int *__single __ended_by(*end)' (aka 'int *__single'))}} + + eb_in(p, *end); + eb_out(p, end); // expected-error{{type of 'end', 'int *__single*__single', is incompatible with parameter of type 'int *__single /* __started_by(start) */ ' (aka 'int *__single')}} + + (void)ret_eb_in(*end); + (void)ret_eb_out(end); // rs-error{{parameter 'end' is implicitly read-only and cannot be passed as an indirect argument due to being used by the '__ended_by' attribute in the return type of 'test_eb_out' ('int *__single __ended_by(*end)' (aka 'int *__single'))}} +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by.c b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by.c new file mode 100644 index 0000000000000..ce000936742b7 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by.c @@ -0,0 +1,436 @@ + +// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +#include + +int side_effect(void); +int get_count(void); +char* get_single_ptr(); +struct cb_with_other_data { + int count; + char* __counted_by(count) buf; + int other; +}; +void consume_cb_with_other_data(struct cb_with_other_data); + +struct NestedCB { + struct cb_with_other_data inner; + int count; + char* __counted_by(count) buf; + int other; +}; + +struct no_attr_with_other_data { + int count; + char* buf; + int other; +}; +_Static_assert(sizeof(struct cb_with_other_data) == sizeof(struct no_attr_with_other_data), "size mismatch"); + +union TransparentUnion { + struct cb_with_other_data cb; + struct no_attr_with_other_data no_cb; +} __attribute__((__transparent_union__)); + +void receive_transparent_union(union TransparentUnion); + + +void no_diag(void) { + // No diagnostics + consume_cb_with_other_data((struct cb_with_other_data){ + 0x0, + 0x0, + 0x0 + }); +} + +struct cb_with_other_data global_no_diags = (struct cb_with_other_data) { + 0x0, + 0x0, + 0x0 +}; + + +struct cb_with_other_data field_initializers_with_side_effects(struct cb_with_other_data* s) { + *s = (struct cb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + struct cb_with_other_data s2 = (struct cb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + consume_cb_with_other_data((struct cb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect()} + ); + consume_cb_with_other_data((struct cb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0} + ); + + (void) (struct cb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0}; + + // no diags for structs without attributes + struct no_attrs { + int count; + char* buf; + }; + (void) (struct no_attrs) { side_effect(), 0x0}; + + // Nested + struct Contains_cb_with_other_data { + struct cb_with_other_data s; + int other; + }; + (void)(struct Contains_cb_with_other_data) { + .s = { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + }, + .other = 0x0 + }; + + // Nested CompoundLiteralExpr + (void)(struct NestedCB) { + // expected-warning@+1{{initializer '(struct cb_with_other_data){.count = 0, .buf = 0, .other = side_effect()}' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .inner = (struct cb_with_other_data) { + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminat}} + .other = side_effect() + }, + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect() + }; + + // Test array initializer list that initializes structs + (void)(struct cb_with_other_data[]){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {0, 0x0, side_effect()}, + {0, 0x0, 0x0} + }; + + union UnionWith_cb_with_other_data { + struct cb_with_other_data u; + int other; + }; + + (void)(union UnionWith_cb_with_other_data) { + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + }; + + // Call a function that takes a transparent union + receive_transparent_union( + // Test very "untransparent" + (union TransparentUnion) {.cb = + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + } + ); + // Call using + receive_transparent_union( + // Transparent + (struct cb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + ); + + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + return (struct cb_with_other_data) { 0, 0x0, side_effect()}; +} + +struct cb_with_other_data global_cb_with_other_data_side_effect_init = + (struct cb_with_other_data) { + .buf = 0x0, + .count = 0, + .other = side_effect() // both-error{{initializer element is not a compile-time constant}} +}; + + +struct cb_with_other_data side_effects_in_ptr(struct cb_with_other_data* s) { + *s = (struct cb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + consume_cb_with_other_data((struct cb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0} + ); + + (void) (struct cb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + (void)(struct NestedCB) { + .inner = (struct cb_with_other_data) { + .count = 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }, + .count = 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }; + + return (struct cb_with_other_data ){ + 0, + // expected-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; +} + +struct cb_with_other_data side_effects_in_count(struct cb_with_other_data* s) { + *s = (struct cb_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + consume_cb_with_other_data((struct cb_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0} + ); + + (void) (struct cb_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + (void)(struct NestedCB) { + .inner = (struct cb_with_other_data) { + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }, + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }; + + return (struct cb_with_other_data ){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; +} + +// To keep this test case small just test the `*s = CompoundLiteralExpr` variant +// in the remaining test cases. + +void constant_neg_count(struct cb_with_other_data* s) { + *s = (struct cb_with_other_data){ + -1, + // expected-error@+1{{negative count value of -1 for 'char *__single __counted_by(count)' (aka 'char *__single')}} + 0x0, + 0x0 + }; +} + +struct cb_with_other_data global_cb_with_other_data_constant_neg_count = + (struct cb_with_other_data) { + // expected-error@+1{{negative count value of -1 for 'global_cb_with_other_data_constant_neg_count.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .count = -1, + .other = 0x0 +}; + +struct NestedCB global_nested_cb_constant_neg_count = (struct NestedCB) { + .inner = (struct cb_with_other_data) { + .count = -1, + // expected-error@+1{{negative count value of -1 for 'global_nested_cb_constant_neg_count.inner.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .other = 0x0 + }, + .count = -1, + // expected-error@+1{{negative count value of -1 for 'global_nested_cb_constant_neg_count.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .other = 0 +}; + +void constant_pos_count_nullptr(struct cb_with_other_data* s) { + *s = (struct cb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with null always fails}} + 0x0, + 0x0 + }; +} + +struct cb_with_other_data global_cb_with_other_data_constant_pos_count_nullptr = + (struct cb_with_other_data) { + // expected-error@+1{{initializing 'global_cb_with_other_data_constant_pos_count_nullptr.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with null always fails}} + .buf = 0x0, + .count = 100, + .other = 0x0 +}; + +struct NestedCB global_nested_cb_constant_post_count_nullptr = (struct NestedCB) { + .inner = (struct cb_with_other_data) { + .count = 100, + // expected-error@+1{{initializing 'global_nested_cb_constant_post_count_nullptr.inner.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with null always fails}} + .buf = 0x0, + .other = 0x0 + }, + .count = 100, + // expected-error@+1{{initializing 'global_nested_cb_constant_post_count_nullptr.buf' of type 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with null always fails}} + .buf = 0x0, + .other = 0 +}; + +void bad_arr_size(struct cb_with_other_data* s) { + char arr[3]; // expected-note{{'arr' declared here}} + *s = (struct cb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with array 'arr' (which has 3 elements) always fails}} + arr, + 0x0 + }; +} + +// Can't refer to non constant expressions at file scope so the bad `count` +// diagnostic doesn't get emitted. +char global_arr[3] = {0}; +struct cb_with_other_data global_cb_with_other_data_bad_arr_size = + (struct cb_with_other_data) { + .buf = global_arr, // both-error{{initializer element is not a compile-time constant}} + .count = 100, + .other = 0x0 +}; + +void bad_count_and_single_ptr_src(struct cb_with_other_data* s, char* ptr) { // expected-note{{consider adding '__counted_by(100)' to 'ptr'}} + *s = (struct cb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __counted_by(count)' (aka 'char *__single') and count value of 100 with 'char *__single' always fails}} + ptr, + 0x0 + }; +} + +// Can't refer to non constant expressions at file scope so the bad `count` +// diagnostic doesn't get emitted. +char* global_ptr; +struct cb_with_other_data global_cb_with_other_data_bad_count_single_ptr = + (struct cb_with_other_data) { + .buf = global_ptr , // both-error{{initializer element is not a compile-time constant}} + .count = 100, + .other = 0x0 +}; + +void bad_implicit_zero_count(struct cb_with_other_data* s, char*__bidi_indexable ptr, struct NestedCB* ncb) { + *s = (struct cb_with_other_data){ + // expected-warning@+1{{possibly initializing 'char *__single __counted_by(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr + }; + + *ncb = (struct NestedCB) { + // expected-warning@+1{{possibly initializing 'char *__single __counted_by(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr, + .inner = (struct cb_with_other_data) { + // expected-warning@+1{{possibly initializing 'char *__single __counted_by(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr + } + }; +} + +void unknown_count_and_single_ptr_src(struct cb_with_other_data* s, char* ptr, struct NestedCB* ncb) { + int count = get_count(); + *s = (struct cb_with_other_data){ + count, // expected-note{{count initialized here}} + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + ptr, + 0x0 + }; + + *ncb = (struct NestedCB) { + .inner = (struct cb_with_other_data) { + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + .buf = ptr, + .count = count // expected-note{{count initialized here}} + }, + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + .buf = ptr, + .count = count // expected-note{{count initialized here}} + }; +} + +void var_init_from_compound_literal_with_side_effect(char*__bidi_indexable ptr) { + // FIXME: This diagnostic is misleading. The actually restriction is the + // compound literal can't contain side-effects but the diagnostic talks about + // "non-constant array". If the side-effect (call to `get_count()`) is removed + // then this error goes away even though the compound literal is still + // non-constant due to initializing from `ptr`. + // both-error@+1{{cannot initialize array of type 'struct cb_with_other_data[]' with non-constant array of type 'struct cb_with_other_data[2]'}} + struct cb_with_other_data arr[] = (struct cb_with_other_data[]){ + {.buf = ptr, .count = 0x0, .other = 0x0}, + // expected-warning@+1{{initializer 'get_count()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {.buf = ptr, .count = 0x0, .other = get_count()}, + }; +} + +void call_null_ptr_cb(int new_count) { + consume_cb_with_other_data((struct cb_with_other_data) { + .buf = (char*)0, + .count = new_count + }); + consume_cb_with_other_data((struct cb_with_other_data) { + .buf = (void*)0, + .count = new_count + }); + consume_cb_with_other_data((struct cb_with_other_data) { + .buf = ((char*)(void*)(char*)0), + .count = new_count + }); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by_or_null.c b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by_or_null.c new file mode 100644 index 0000000000000..508bd058bdc4d --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-counted_by_or_null.c @@ -0,0 +1,417 @@ + +// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +#include + +int side_effect(void); +int get_count(void); +char* get_single_ptr(); +struct cbon_with_other_data { + int count; + char* __counted_by_or_null(count) buf; + int other; +}; +void consume_cbon_with_other_data(struct cbon_with_other_data); + +struct NestedCBON { + struct cbon_with_other_data inner; + int count; + char* __counted_by_or_null(count) buf; + int other; +}; + +struct no_attr_with_other_data { + int count; + char* buf; + int other; +}; +_Static_assert(sizeof(struct cbon_with_other_data) == sizeof(struct no_attr_with_other_data), "size mismatch"); + +union TransparentUnion { + struct cbon_with_other_data cb; + struct no_attr_with_other_data no_cb; +} __attribute__((__transparent_union__)); + +void receive_transparent_union(union TransparentUnion); + + +void no_diag(void) { + // No diagnostics + consume_cbon_with_other_data((struct cbon_with_other_data){ + 0x0, + 0x0, + 0x0 + }); +} + +struct cbon_with_other_data global_no_diags = (struct cbon_with_other_data) { + 0x0, + 0x0, + 0x0 +}; + +struct cbon_with_other_data field_initializers_with_side_effects(struct cbon_with_other_data* s) { + *s = (struct cbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + struct cbon_with_other_data s2 = (struct cbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + consume_cbon_with_other_data((struct cbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect()} + ); + consume_cbon_with_other_data((struct cbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0} + ); + + (void) (struct cbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0}; + + // no diags for structs without attributes + struct no_attrs { + int count; + char* buf; + }; + (void) (struct no_attrs) { side_effect(), 0x0}; + + // Nested + struct Contains_cbon_with_other_data { + struct cbon_with_other_data s; + int other; + }; + (void)(struct Contains_cbon_with_other_data) { + .s = { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + }, + .other = 0x0 + }; + + // Nested CompoundLiteralExpr + (void)(struct NestedCBON) { + // expected-warning@+1{{initializer '(struct cbon_with_other_data){.count = 0, .buf = 0, .other = side_effect()}' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .inner = (struct cbon_with_other_data) { + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminat}} + .other = side_effect() + }, + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect() + }; + + // Test array initializer list that initializes structs + (void)(struct cbon_with_other_data[]){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {0, 0x0, side_effect()}, + {0, 0x0, 0x0} + }; + + union UnionWith_cbon_with_other_data { + struct cbon_with_other_data u; + int other; + }; + + (void)(union UnionWith_cbon_with_other_data) { + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + }; + + // Call a function that takes a transparent union + receive_transparent_union( + // Test very "untransparent" + (union TransparentUnion) {.cb = + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + } + ); + // Call using + receive_transparent_union( + // Transparent + (struct cbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + ); + + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + return (struct cbon_with_other_data) { 0, 0x0, side_effect()}; +} + +struct cbon_with_other_data global_cbon_with_other_data_side_effect_init = + (struct cbon_with_other_data) { + .buf = 0x0, + .count = 0, + .other = side_effect() // both-error{{initializer element is not a compile-time constant}} +}; + + +struct cbon_with_other_data side_effects_in_ptr(struct cbon_with_other_data* s) { + *s = (struct cbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + consume_cbon_with_other_data((struct cbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0} + ); + + (void) (struct cbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + (void)(struct NestedCBON) { + .inner = (struct cbon_with_other_data) { + .count = 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }, + .count = 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }; + + return (struct cbon_with_other_data ){ + 0, + // expected-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; +} + +struct cbon_with_other_data side_effects_in_count(struct cbon_with_other_data* s) { + *s = (struct cbon_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + consume_cbon_with_other_data((struct cbon_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0} + ); + + (void) (struct cbon_with_other_data){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + (void)(struct NestedCBON) { + .inner = (struct cbon_with_other_data) { + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }, + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }; + + return (struct cbon_with_other_data ){ + // expected-error@+1{{initalizer for count with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; +} + +// To keep this test case small just test the `*s = CompoundLiteralExpr` variant +// in the remaining test cases. + +void constant_neg_count(struct cbon_with_other_data* s) { + *s = (struct cbon_with_other_data){ + -1, + 0x0, // ok + 0x0 + }; +} + +struct cbon_with_other_data global_cbon_with_other_data_constant_neg_count = + (struct cbon_with_other_data) { + .buf = 0x0, // ok + .count = -1, + .other = 0x0 +}; + +struct NestedCBON global_nested_cbon_constant_neg_count = (struct NestedCBON) { + .inner = (struct cbon_with_other_data) { + .count = -1, + .buf = 0x0, // OK + .other = 0x0 + }, + .count = -1, + .buf = 0x0, + .other = 0 +}; + +void constant_pos_count_nullptr(struct cbon_with_other_data* s) { + *s = (struct cbon_with_other_data){ + 100, + 0x0, // OK + 0x0 + }; +} + +struct cbon_with_other_data global_cbon_with_other_data_constant_pos_count_nullptr = + (struct cbon_with_other_data) { + .buf = 0x0, // ok + .count = 100, + .other = 0x0 +}; + +struct NestedCBON global_nested_cbon_constant_post_count_nullptr = (struct NestedCBON) { + .inner = (struct cbon_with_other_data) { + .count = 100, + .buf = 0x0, // OK + .other = 0x0 + }, + .count = 100, + .buf = 0x0, // OK + .other = 0 +}; + +void bad_arr_size(struct cbon_with_other_data* s) { + char arr[3]; // expected-note{{'arr' declared here}} + *s = (struct cbon_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') and count value of 100 with array 'arr' (which has 3 elements) always fails}} + arr, + 0x0 + }; +} + +// Can't refer to non constant expressions at file scope so the bad `count` +// diagnostic doesn't get emitted. +char global_arr[3] = {0}; +struct cbon_with_other_data global_cbon_with_other_data_bad_arr_size = + (struct cbon_with_other_data) { + .buf = global_arr, // both-error{{initializer element is not a compile-time constant}} + .count = 100, + .other = 0x0 +}; + +void bad_count_and_single_ptr_src(struct cbon_with_other_data* s, char* ptr) { + *s = (struct cbon_with_other_data){ + 100, + // No diag because `ptr` might be null + ptr, + 0x0 + }; +} + +void bad_implicit_zero_count(struct cbon_with_other_data* s, char*__bidi_indexable ptr, struct NestedCBON* ncbon) { + *s = (struct cbon_with_other_data){ + // expected-warning@+1{{possibly initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr + }; + + *ncbon = (struct NestedCBON) { + // expected-warning@+1{{possibly initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr, + .inner = (struct cbon_with_other_data) { + // expected-warning@+1{{possibly initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') and implicit count value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set count value to 0 to remove this warning}} + .buf = ptr + } + }; +} + +void unknown_count_and_single_ptr_src(struct cbon_with_other_data* s, char* ptr, struct NestedCBON* ncbon) { + int count = get_count(); + *s = (struct cbon_with_other_data){ + count, // expected-note{{count initialized here}} + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + ptr, + 0x0 + }; + + *ncbon = (struct NestedCBON) { + .inner = (struct cbon_with_other_data) { + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + .buf = ptr, + .count = count // expected-note{{count initialized here}} + }, + // expected-warning@+1{{count value is not statically known: initializing 'char *__single __counted_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any count other than 0 or 1}} + .buf = ptr, + .count = count // expected-note{{count initialized here}} + }; +} + +void var_init_from_compound_literal_with_side_effect(char*__bidi_indexable ptr) { + // FIXME: This diagnostic is misleading. The actually restriction is the + // compound literal can't contain side-effects but the diagnostic talks about + // "non-constant array". If the side-effect (call to `get_count()`) is removed + // then this error goes away even though the compound literal is still + // non-constant due to initializing from `ptr`. + // both-error@+1{{cannot initialize array of type 'struct cbon_with_other_data[]' with non-constant array of type 'struct cbon_with_other_data[2]'}} + struct cbon_with_other_data arr[] = (struct cbon_with_other_data[]){ + {.buf = ptr, .count = 0x0, .other = 0x0}, + // expected-warning@+1{{initializer 'get_count()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {.buf = ptr, .count = 0x0, .other = get_count()}, + }; +} + +void call_null_ptr_cbon(int new_count) { + consume_cbon_with_other_data((struct cbon_with_other_data) { + .buf = (char*)0, + .count = new_count + }); + consume_cbon_with_other_data((struct cbon_with_other_data) { + .buf = (void*)0, + .count = new_count + }); + consume_cbon_with_other_data((struct cbon_with_other_data) { + .buf = ((char*)(void*)(char*)0), + .count = new_count + }); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-ended_by.c b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-ended_by.c new file mode 100644 index 0000000000000..ab95be87121db --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-ended_by.c @@ -0,0 +1,324 @@ + +// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +#include + +int side_effect(void); +int get_count(void); +char* get_single_ptr(); +struct eb_with_other_data { + char* __ended_by(end) start; + char* end; + int other; +}; +void consume_eb_with_other_data(struct eb_with_other_data); + +struct NestedEB { + struct eb_with_other_data inner; + char* end; + char* __ended_by(end) start; + int other; +}; + +struct no_attr_with_other_data { + char* end; + char* start; + int other; +}; +_Static_assert(sizeof(struct eb_with_other_data) == sizeof(struct no_attr_with_other_data), "size mismatch"); + +union TransparentUnion { + struct eb_with_other_data cb; + struct no_attr_with_other_data no_cb; +} __attribute__((__transparent_union__)); + +void receive_transparent_union(union TransparentUnion); + + +void no_diag(void) { + // No diagnostics + consume_eb_with_other_data((struct eb_with_other_data){ + 0x0, + 0x0, + 0x0 + }); +} + +struct eb_with_other_data global_no_diags = (struct eb_with_other_data) { + // FIXME: This should be allowed. rdar://81135826 + 0x0, // both-error{{initializer element is not a compile-time constant}} + 0x0, + 0x0 +}; + +struct eb_with_other_data field_initializers_with_side_effects(struct eb_with_other_data* s) { + *s = (struct eb_with_other_data){ + 0x0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + struct eb_with_other_data s2 = (struct eb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + consume_eb_with_other_data((struct eb_with_other_data){ + 0x0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect()} + ); + consume_eb_with_other_data((struct eb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0} + ); + + (void) (struct eb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0}; + + // no diags for structs without attributes + struct no_attrs { + char* start; + char* end; + int other; + }; + (void) (struct no_attrs) { 0x0, 0x0, side_effect()}; + + // Nested + struct Contains_eb_with_other_data { + struct eb_with_other_data s; + int other; + }; + (void)(struct Contains_eb_with_other_data) { + .s = { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0 + }, + .other = 0x0 + }; + + // Nested CompoundLiteralExpr + (void)(struct NestedEB) { + // expected-warning@+1{{initializer '(struct eb_with_other_data){.start = 0, .end = 0, .other = side_effect()}' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .inner = (struct eb_with_other_data) { + .start = 0x0, + .end = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminat}} + .other = side_effect() + }, + .start = 0x0, + .end = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect() + }; + + // Test array initializer list that initializes structs + (void)(struct eb_with_other_data[]){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {0x0, 0x0, side_effect()}, + {0x0, 0x0, 0x0} + }; + + union UnionWith_eb_with_other_data { + struct eb_with_other_data u; + int other; + }; + + (void)(union UnionWith_eb_with_other_data) { + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0 + } + }; + + // Call a function that takes a transparent union + receive_transparent_union( + // Test very "untransparent" + (union TransparentUnion) {.cb = + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0 + } + } + ); + // Call using + receive_transparent_union( + // Transparent + (struct eb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .start = 0x0, + .end = 0x0 + } + ); + + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + return (struct eb_with_other_data) { 0x0, 0x0, side_effect()}; +}; + +struct eb_with_other_data global_eb_with_other_data_side_effect_init = + (struct eb_with_other_data) { + // FIXME: Location of first non-constant is wrong (rdar://81135826) + .start = 0x0, // both-error{{initializer element is not a compile-time constant}} + .end = 0x0, + .other = side_effect() +}; + +struct eb_with_other_data side_effects_in_ptrs(struct eb_with_other_data* s) { + *s = (struct eb_with_other_data){ + get_single_ptr(), // expected-error{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + get_single_ptr(), // expected-error{{initalizer for end pointer with side effects is not yet supported}} + 0x0 + }; + + consume_eb_with_other_data( + (struct eb_with_other_data){ + get_single_ptr(), // expected-error{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + get_single_ptr(), // expected-error{{initalizer for end pointer with side effects is not yet supported}} + 0x0 + } + ); + + (void)(struct eb_with_other_data){ + get_single_ptr(), // expected-error{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + get_single_ptr(), // expected-error{{initalizer for end pointer with side effects is not yet supported}} + 0x0 + }; + + (void)(struct NestedEB) { + .inner = (struct eb_with_other_data) { + // expected-error@+1{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + .start = get_single_ptr(), + // expected-error@+1{{initalizer for end pointer with side effects is not yet supported}} + .end = get_single_ptr(), + .other = 0 + }, + // expected-error@+1{{initalizer for end pointer with side effects is not yet supported}} + .end = get_single_ptr(), + // expected-error@+1{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + .start = get_single_ptr(), + .other = 0 + }; + + return (struct eb_with_other_data){ + get_single_ptr(), // expected-error{{initalizer for '__ended_by' pointer with side effects is not yet supported}} + get_single_ptr(), // expected-error{{initalizer for end pointer with side effects is not yet supported}} + 0x0 + }; +} + +// To keep this test case small just test the `*s = CompoundLiteralExpr` variant +// in the remaining test cases. + +void partial_init_start(struct eb_with_other_data* s, char* start, struct NestedEB* neb) { + // expected-warning@+1{{implicitly initializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} + *s = (struct eb_with_other_data){ .start = start }; + + *neb = (struct NestedEB) { + .inner = (struct eb_with_other_data) { + .start = start + },// expected-warning{{implicitly initializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} + .start = start + }; // expected-warning{{implicitly initializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} +} + + +// Partial init diagnostic isn't emitted because `global_start_ptr` isn't constant +char* global_start_ptr; +struct eb_with_other_data global_eb_partial_init = + (struct eb_with_other_data) { + .other = 0x0, + .start = global_start_ptr // both-error{{initializer element is not a compile-time constant}} +}; +struct eb_with_other_data global_eb_partial_init2 = + (struct eb_with_other_data) { + .other = 0x0, + // FIXME: This should be treated as a constant (rdar://81135826) + .start = __unsafe_forge_bidi_indexable(char*, 0x1, 4) // both-error{{initializer element is not a compile-time constant}} +}; + + +void end_is_null(struct eb_with_other_data* s, char* start, struct NestedEB* neb) { + // expected-warning@+1{{initializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} + *s = (struct eb_with_other_data){ .start = start, .end = 0x0 }; + + *neb = (struct NestedEB) { + .inner = (struct eb_with_other_data) { + .start = start, + // expected-warning@+1{{nitializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} + .end = 0x0 + }, + .start = start, + // expected-warning@+1{{nitializing field 'end' of type 'char *__single /* __started_by(start) */ ' (aka 'char *__single') to NULL while 'start' is initialized with a value rarely succeeds}} + .end = 0x0 + }; +} + +void partial_init_ended(struct eb_with_other_data* s, char* end, struct NestedEB* neb) { + // expected-warning@+1{{implicitly initializing field 'start' of type 'char *__single __ended_by(end)' (aka 'char *__single') to NULL while 'end' is initialized with a value rarely succeeds}} + *s = (struct eb_with_other_data){ .end = end }; + + + *neb = (struct NestedEB) { + .inner = (struct eb_with_other_data) { + .end = end + }, // expected-warning{{implicitly initializing field 'start' of type 'char *__single __ended_by(end)' (aka 'char *__single') to NULL while 'end' is initialized with a value rarely succeeds}} + .end = end + }; // expected-warning{{implicitly initializing field 'start' of type 'char *__single __ended_by(end)' (aka 'char *__single') to NULL while 'end' is initialized with a value rarely succeeds}} +} + +void start_is_null(struct eb_with_other_data* s, char* end) { + // expected-warning@+1{{initializing field 'start' of type 'char *__single __ended_by(end)' (aka 'char *__single') to NULL while 'end' is initialized with a value rarely succeeds}} + *s = (struct eb_with_other_data){ .start = 0x0, .end = end}; +} + + +void partial_init_other(struct eb_with_other_data* s, struct NestedEB* neb) { + // OK + *s = (struct eb_with_other_data){ .other = 0x0 }; + *neb = (struct NestedEB) { + .inner = (struct eb_with_other_data) {.other = 0x0}, + .other = 0x0 + }; +} + +void implicit_init_all(struct eb_with_other_data* s, struct NestedEB* neb) { + // OK + *s = (struct eb_with_other_data){0}; + *neb = (struct NestedEB) {0}; + *neb = (struct NestedEB) { + .inner = (struct eb_with_other_data) {0} + }; +} + +void var_init_from_compound_literal_with_side_effect(char*__bidi_indexable ptr) { + // FIXME: This diagnostic is misleading. The actually restriction is the + // compound literal can't contain side-effects but the diagnostic talks about + // "non-constant array". If the side-effect (call to `get_count()`) is removed + // then this error goes away even though the compound literal is still + // non-constant due to initializing from `ptr`. + // both-error@+1{{cannot initialize array of type 'struct eb_with_other_data[]' with non-constant array of type 'struct eb_with_other_data[2]'}} + struct eb_with_other_data arr[] = (struct eb_with_other_data[]){ + {.start = ptr, .end = ptr + 1, .other = 0x0}, + // expected-warning@+1{{initializer 'get_count()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {.start = ptr, .end = ptr + 1, .other = get_count()}, + }; +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by.c b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by.c new file mode 100644 index 0000000000000..545114e587391 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by.c @@ -0,0 +1,432 @@ + +// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +#include + +int side_effect(void); +int get_count(void); +char* get_single_ptr(); +struct sb_with_other_data { + int count; + char* __sized_by(count) buf; + int other; +}; +void consume_sb_with_other_data(struct sb_with_other_data); + +struct NestedSB { + struct sb_with_other_data inner; + int count; + char* __sized_by(count) buf; + int other; +}; + +struct no_attr_with_other_data { + int count; + char* buf; + int other; +}; +_Static_assert(sizeof(struct sb_with_other_data) == sizeof(struct no_attr_with_other_data), "size mismatch"); + +union TransparentUnion { + struct sb_with_other_data cb; + struct no_attr_with_other_data no_cb; +} __attribute__((__transparent_union__)); + +void receive_transparent_union(union TransparentUnion); + + +void no_diag(void) { + // No diagnostics + consume_sb_with_other_data((struct sb_with_other_data){ + 0x0, + 0x0, + 0x0 + }); +} + +struct sb_with_other_data global_no_diags = (struct sb_with_other_data) { + 0x0, + 0x0, + 0x0 +}; + + +struct sb_with_other_data field_initializers_with_side_effects(struct sb_with_other_data* s) { + *s = (struct sb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + struct sb_with_other_data s2 = (struct sb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + consume_sb_with_other_data((struct sb_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect()} + ); + consume_sb_with_other_data((struct sb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0} + ); + + (void) (struct sb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0}; + + // no diags for structs without attributes + struct no_attrs { + int count; + char* buf; + }; + (void) (struct no_attrs) { side_effect(), 0x0}; + + // Nested + struct Contains_sb_with_other_data { + struct sb_with_other_data s; + int other; + }; + (void)(struct Contains_sb_with_other_data) { + .s = { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + }, + .other = 0x0 + }; + + // Nested CompoundLiteralExpr + (void)(struct NestedSB) { + // expected-warning@+1{{initializer '(struct sb_with_other_data){.count = 0, .buf = 0, .other = side_effect()}' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .inner = (struct sb_with_other_data) { + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminat}} + .other = side_effect() + }, + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect() + }; + + // Test array initializer list that initializes structs + (void)(struct sb_with_other_data[]){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {0, 0x0, side_effect()}, + {0, 0x0, 0x0} + }; + + union UnionWith_sb_with_other_data { + struct sb_with_other_data u; + int other; + }; + + (void)(union UnionWith_sb_with_other_data) { + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + }; + + // Call a function that takes a transparent union + receive_transparent_union( + // Test very "untransparent" + (union TransparentUnion) {.cb = + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + } + ); + // Call using + receive_transparent_union( + // Transparent + (struct sb_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + ); + + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + return (struct sb_with_other_data) { 0, 0x0, side_effect()}; +} + +struct sb_with_other_data global_sb_with_other_data_side_effect_init = + (struct sb_with_other_data) { + .buf = 0x0, + .count = 0, + .other = side_effect() // both-error{{initializer element is not a compile-time constant}} +}; + + +struct sb_with_other_data side_effects_in_ptr(struct sb_with_other_data* s) { + *s = (struct sb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + consume_sb_with_other_data((struct sb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0} + ); + + (void) (struct sb_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + (void)(struct NestedSB) { + .inner = (struct sb_with_other_data) { + .count = 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }, + .count = 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }; + + return (struct sb_with_other_data ){ + 0, + // expected-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; +} + +struct sb_with_other_data side_effects_in_count(struct sb_with_other_data* s) { + *s = (struct sb_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + consume_sb_with_other_data((struct sb_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0} + ); + + (void) (struct sb_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + (void)(struct NestedSB) { + .inner = (struct sb_with_other_data) { + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }, + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }; + + return (struct sb_with_other_data ){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; +} + + +// To keep this test case small just test the `*s = CompoundLiteralExpr` variant +// in the remaining test cases. + +void constant_neg_count(struct sb_with_other_data* s) { + *s = (struct sb_with_other_data){ + -1, + // expected-error@+1{{negative size value of -1 for 'char *__single __sized_by(count)' (aka 'char *__single')}} + 0x0, + 0x0 + }; +} + +struct sb_with_other_data global_sb_with_other_data_constant_neg_count = + (struct sb_with_other_data) { + // expected-error@+1{{negative size value of -1 for 'global_sb_with_other_data_constant_neg_count.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .count = -1, + .other = 0x0 +}; + +struct NestedSB global_nested_sb_constant_neg_count = (struct NestedSB) { + .inner = (struct sb_with_other_data) { + .count = -1, + // expected-error@+1{{negative size value of -1 for 'global_nested_sb_constant_neg_count.inner.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .other = 0x0 + }, + .count = -1, + // expected-error@+1{{negative size value of -1 for 'global_nested_sb_constant_neg_count.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single')}} + .buf = 0x0, + .other = 0 +}; + + +void constant_pos_count_nullptr(struct sb_with_other_data* s) { + *s = (struct sb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with null always fails}} + 0x0, + 0x0 + }; +} + + +struct sb_with_other_data global_sb_with_other_data_constant_pos_count_nullptr = + (struct sb_with_other_data) { + // expected-error@+1{{initializing 'global_sb_with_other_data_constant_pos_count_nullptr.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with null always fails}} + .buf = 0x0, + .count = 100, + .other = 0x0 +}; + +struct NestedSB global_nested_sb_constant_pos_count_nullptr = (struct NestedSB) { + .inner = (struct sb_with_other_data) { + .count = 100, + // expected-error@+1{{initializing 'global_nested_sb_constant_pos_count_nullptr.inner.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with null always fails}} + .buf = 0x0, + .other = 0x0 + }, + .count = 100, + // expected-error@+1{{initializing 'global_nested_sb_constant_pos_count_nullptr.buf' of type 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with null always fails}} + .buf = 0x0, + .other = 0 +}; + + +void bad_arr_size(struct sb_with_other_data* s) { + char arr[3]; // expected-note{{'arr' declared here}} + *s = (struct sb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with array 'arr' (which has 3 bytes) always fails}} + arr, + 0x0 + }; +} + +// Can't refer to non constant expressions at file scope so the bad `count` +// diagnostic doesn't get emitted. +char global_arr[3] = {0}; +struct sb_with_other_data global_sb_with_other_data_bad_arr_size = + (struct sb_with_other_data) { + .buf = global_arr, // both-error{{initializer element is not a compile-time constant}} + .count = 100, + .other = 0x0 +}; + +void bad_count_and_single_ptr_src(struct sb_with_other_data* s, char* ptr) { // expected-note{{consider adding '__sized_by(100)' to 'ptr'}} + *s = (struct sb_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __sized_by(count)' (aka 'char *__single') and size value of 100 with 'char *__single' and pointee of size 1 always fails}} + ptr, + 0x0 + }; +} + + +void bad_implicit_zero_count(struct sb_with_other_data* s, char*__bidi_indexable ptr, struct NestedSB* nsb) { + *s = (struct sb_with_other_data){ + // expected-warning@+1{{'char *__single __sized_by(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr + }; + + *nsb = (struct NestedSB) { + // expected-warning@+1{{possibly initializing 'char *__single __sized_by(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr, + .inner = (struct sb_with_other_data) { + // expected-warning@+1{{possibly initializing 'char *__single __sized_by(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr + } + }; +} + + +void unknown_count_and_single_ptr_src(struct sb_with_other_data* s, char* ptr, struct NestedSB* nsb) { + int count = get_count(); + *s = (struct sb_with_other_data){ + count, // expected-note{{size initialized here}} + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1}} + ptr, + 0x0 + }; + + *nsb = (struct NestedSB) { + .inner = (struct sb_with_other_data) { + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1}} + .buf = ptr, + .count = count // expected-note{{size initialized here}} + }, + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1}} + .buf = ptr, + .count = count // expected-note{{size initialized here}} + }; +} + +void var_init_from_compound_literal_with_side_effect(char*__bidi_indexable ptr) { + // FIXME: This diagnostic is misleading. The actually restriction is the + // compound literal can't contain side-effects but the diagnostic talks about + // "non-constant array". If the side-effect (call to `get_count()`) is removed + // then this error goes away even though the compound literal is still + // non-constant due to initializing from `ptr`. + // both-error@+1{{cannot initialize array of type 'struct sb_with_other_data[]' with non-constant array of type 'struct sb_with_other_data[2]'}} + struct sb_with_other_data arr[] = (struct sb_with_other_data[]){ + {.buf = ptr, .count = 0x0, .other = 0x0}, + // expected-warning@+1{{initializer 'get_count()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {.buf = ptr, .count = 0x0, .other = get_count()}, + }; +} + +void call_null_ptr_sb(int new_count) { + consume_sb_with_other_data((struct sb_with_other_data) { + .buf = (char*)0, + .count = new_count + }); + consume_sb_with_other_data((struct sb_with_other_data) { + .buf = (void*)0, + .count = new_count + }); + consume_sb_with_other_data((struct sb_with_other_data) { + .buf = ((char*)(void*)(char*)0), + .count = new_count + }); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by_or_null.c b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by_or_null.c new file mode 100644 index 0000000000000..fec49814d610c --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/compound-literal-sized_by_or_null.c @@ -0,0 +1,425 @@ + +// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +#include + +int side_effect(void); +int get_count(void); +char* get_single_ptr(); +struct sbon_with_other_data { + int count; + char* __sized_by_or_null(count) buf; + int other; +}; +void consume_sbon_with_other_data(struct sbon_with_other_data); + +struct NestedSBON { + struct sbon_with_other_data inner; + int count; + char* __sized_by_or_null(count) buf; + int other; +}; + +struct no_attr_with_other_data { + int count; + char* buf; + int other; +}; +_Static_assert(sizeof(struct sbon_with_other_data) == sizeof(struct no_attr_with_other_data), "size mismatch"); + +union TransparentUnion { + struct sbon_with_other_data cb; + struct no_attr_with_other_data no_cb; +} __attribute__((__transparent_union__)); + +void receive_transparent_union(union TransparentUnion); + + +void no_diag(void) { + // No diagnostics + consume_sbon_with_other_data((struct sbon_with_other_data){ + 0x0, + 0x0, + 0x0 + }); +} + +struct sbon_with_other_data global_no_diags = (struct sbon_with_other_data) { + 0x0, + 0x0, + 0x0 +}; + +struct sbon_with_other_data field_initializers_with_side_effects(struct sbon_with_other_data* s) { + *s = (struct sbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + struct sbon_with_other_data s2 = (struct sbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect() + }; + + consume_sbon_with_other_data((struct sbon_with_other_data){ + 0, + 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + side_effect()} + ); + consume_sbon_with_other_data((struct sbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0} + ); + + (void) (struct sbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0}; + + // no diags for structs without attributes + struct no_attrs { + int count; + char* buf; + }; + (void) (struct no_attrs) { side_effect(), 0x0}; + + // Nested + struct Contains_sbon_with_other_data { + struct sbon_with_other_data s; + int other; + }; + (void)(struct Contains_sbon_with_other_data) { + .s = { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + }, + .other = 0x0 + }; + + // Nested CompoundLiteralExpr + (void)(struct NestedSBON) { + // expected-warning@+1{{initializer '(struct sbon_with_other_data){.count = 0, .buf = 0, .other = side_effect()}' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .inner = (struct sbon_with_other_data) { + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminat}} + .other = side_effect() + }, + .count = 0, + .buf = 0x0, + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect() + }; + + // Test array initializer list that initializes structs + (void)(struct sbon_with_other_data[]){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {0, 0x0, side_effect()}, + {0, 0x0, 0x0} + }; + + union UnionWith_sbon_with_other_data { + struct sbon_with_other_data u; + int other; + }; + + (void)(union UnionWith_sbon_with_other_data) { + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + }; + + // Call a function that takes a transparent union + receive_transparent_union( + // Test very "untransparent" + (union TransparentUnion) {.cb = + { + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + } + ); + // Call using + receive_transparent_union( + // Transparent + (struct sbon_with_other_data){ + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + .other = side_effect(), + .buf = 0x0, + .count = 0 + } + ); + + // expected-warning@+1{{initializer 'side_effect()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + return (struct sbon_with_other_data) { 0, 0x0, side_effect()}; +} + +struct sbon_with_other_data global_sbon_with_other_data_side_effect_init = + (struct sbon_with_other_data) { + .buf = 0x0, + .count = 0, + .other = side_effect() // both-error{{initializer element is not a compile-time constant}} +}; + + +struct sbon_with_other_data side_effects_in_ptr(struct sbon_with_other_data* s) { + *s = (struct sbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + consume_sbon_with_other_data((struct sbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0} + ); + + (void) (struct sbon_with_other_data){ + 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; + + (void)(struct NestedSBON) { + .inner = (struct sbon_with_other_data) { + .count = 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }, + .count = 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + .buf = get_single_ptr(), + .other = 0 + }; + + return (struct sbon_with_other_data ){ + 0, + // expected-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + get_single_ptr(), + 0x0 + }; +} + +struct sbon_with_other_data side_effects_in_count(struct sbon_with_other_data* s) { + *s = (struct sbon_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + consume_sbon_with_other_data((struct sbon_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0} + ); + + (void) (struct sbon_with_other_data){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; + + (void)(struct NestedSBON) { + .inner = (struct sbon_with_other_data) { + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }, + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + .count = get_count(), + .buf = 0x0, + .other = 0 + }; + + return (struct sbon_with_other_data ){ + // expected-error@+1{{initalizer for size with side effects is not yet supported}} + get_count(), + 0x0, + 0x0 + }; +} + + +// To keep this test case small just test the `*s = CompoundLiteralExpr` variant +// in the remaining test cases. + +void constant_neg_count(struct sbon_with_other_data* s) { + *s = (struct sbon_with_other_data){ + -1, + // ok + 0x0, + 0x0 + }; +} + +struct sbon_with_other_data global_sbon_with_other_data_constant_neg_count = + (struct sbon_with_other_data) { + .buf = 0x0, // ok + .count = -1, + .other = 0x0 +}; + +struct NestedSBON global_nested_sbon_constant_neg_count = (struct NestedSBON) { + .inner = (struct sbon_with_other_data) { + .count = -1, + .buf = 0x0, // OK + .other = 0x0 + }, + .count = -1, + .buf = 0x0, // OK + .other = 0 +}; + + + +void constant_pos_count_nullptr(struct sbon_with_other_data* s) { + *s = (struct sbon_with_other_data){ + 100, + // ok + 0x0, + 0x0 + }; +} + +struct sbon_with_other_data global_sbon_with_other_data_constant_pos_count_nullptr = + (struct sbon_with_other_data) { + .buf = 0x0, // ok + .count = 100, + .other = 0x0 +}; + +struct NestedSBON global_nested_sbon_constant_pos_count_nullptr = (struct NestedSBON) { + .inner = (struct sbon_with_other_data) { + .count = 100, + .buf = 0x0, // OK + .other = 0x0 + }, + .count = 100, + .buf = 0x0, // OK + .other = 0 +}; + + +void bad_arr_size(struct sbon_with_other_data* s) { + char arr[3]; // expected-note{{'arr' declared here}} + *s = (struct sbon_with_other_data){ + 100, + // expected-error@+1{{initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') and size value of 100 with array 'arr' (which has 3 bytes) always fails}} + arr, + 0x0 + }; +} + +// Can't refer to non constant expressions at file scope so the bad `count` +// diagnostic doesn't get emitted. +char global_arr[3] = {0}; +struct sbon_with_other_data global_sbon_with_other_data_bad_arr_size = + (struct sbon_with_other_data) { + .buf = global_arr, // both-error{{initializer element is not a compile-time constant}} + .count = 100, + .other = 0x0 +}; + + +void bad_count_and_single_ptr_src(struct sbon_with_other_data* s, char* ptr) { + *s = (struct sbon_with_other_data){ + 100, + ptr, + 0x0 + }; +} + + +void bad_implicit_zero_count(struct sbon_with_other_data* s, char*__bidi_indexable ptr, struct NestedSBON* nsbon) { + *s = (struct sbon_with_other_data){ + // expected-warning@+1{{'char *__single __sized_by_or_null(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr + }; + + *nsbon = (struct NestedSBON) { + // expected-warning@+1{{possibly initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr, + .inner = (struct sbon_with_other_data) { + // expected-warning@+1{{possibly initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') and implicit size value of 0 with non-null, which creates a non-dereferenceable pointer; explicitly set size value to 0 to remove this warning}} + .buf = ptr + } + }; +} + + +void unknown_count_and_single_ptr_src(struct sbon_with_other_data* s, char* ptr, struct NestedSBON* nsbon) { + int count = get_count(); + *s = (struct sbon_with_other_data){ + count, // expected-note{{size initialized here}} + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1}} + ptr, + 0x0 + }; + + *nsbon = (struct NestedSBON) { + .inner = (struct sbon_with_other_data) { + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1 unless the pointer is null}} + .buf = ptr, + .count = count // expected-note{{size initialized here}} + }, + // expected-warning@+1{{size value is not statically known: initializing 'char *__single __sized_by_or_null(count)' (aka 'char *__single') with 'char *__single' is invalid for any size greater than 1 unless the pointer is null}} + .buf = ptr, + .count = count // expected-note{{size initialized here}} + }; +} + +void var_init_from_compound_literal_with_side_effect(char*__bidi_indexable ptr) { + // FIXME: This diagnostic is misleading. The actually restriction is the + // compound literal can't contain side-effects but the diagnostic talks about + // "non-constant array". If the side-effect (call to `get_count()`) is removed + // then this error goes away even though the compound literal is still + // non-constant due to initializing from `ptr`. + // both-error@+1{{cannot initialize array of type 'struct sbon_with_other_data[]' with non-constant array of type 'struct sbon_with_other_data[2]'}} + struct sbon_with_other_data arr[] = (struct sbon_with_other_data[]){ + {.buf = ptr, .count = 0x0, .other = 0x0}, + // expected-warning@+1{{initializer 'get_count()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}} + {.buf = ptr, .count = 0x0, .other = get_count()}, + }; +} + +void call_null_ptr_sbon(int new_count) { + consume_sbon_with_other_data((struct sbon_with_other_data) { + .buf = (char*)0, + .count = new_count + }); + consume_sbon_with_other_data((struct sbon_with_other_data) { + .buf = (void*)0, + .count = new_count + }); + consume_sbon_with_other_data((struct sbon_with_other_data) { + .buf = ((char*)(void*)(char*)0), + .count = new_count + }); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/counted-by-ptr-arith-constant-count.c b/clang/test/BoundsSafety-legacy-checks/Sema/counted-by-ptr-arith-constant-count.c new file mode 100644 index 0000000000000..78fc29721327e --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/counted-by-ptr-arith-constant-count.c @@ -0,0 +1,767 @@ + + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=indirect_count_update -verify=expected,legacy,extra %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=compound_literal_init -verify=expected,legacy,cli %s +#include + +void consume_cb(int* __counted_by(3) p); +void consume_cbon(int* __counted_by_or_null(3) p); + +struct cb { + int count; + int* __counted_by(count) buf; +}; + +struct cbon { + int count; + int* __counted_by_or_null(count) buf; +}; + +void side_effect(void); + +int global_arr [2] = {0}; +// expected-note@+2 4{{__counted_by attribute is here}} +// extra-note@+1 2{{__counted_by attribute is here}} +int*__counted_by(2) global_cb = global_arr; +// expected-note@+2 4{{__counted_by_or_null attribute is here}} +// extra-note@+1 2{{__counted_by_or_null attribute is here}} +int*__counted_by_or_null(2) global_cbon = global_arr; + +const int const_size = 2; +// expected-note@+2 4{{__counted_by attribute is here}} +// extra-note@+1 2{{__counted_by attribute is here}} +int*__counted_by(const_size) global_cb_const_qual_count = global_arr; +// expected-note@+2 4{{__counted_by_or_null attribute is here}} +// extra-note@+1 2{{__counted_by_or_null attribute is here}} +int*__counted_by_or_null(const_size) global_cbon_const_qual_count = global_arr; + +// expected-note@+2 4{{__counted_by attribute is here}} +// extra-note@+1 2{{__counted_by attribute is here}} +int*__counted_by(1+1) global_cb_opo = global_arr; +// expected-note@+2 4{{__counted_by_or_null attribute is here}} +// extra-note@+1 2{{__counted_by_or_null attribute is here}} +int*__counted_by_or_null(1+1) global_cbon_opo = global_arr; + +// legacy-note@+3 1{{__counted_by attribute is here}} +// expected-note@+2 8{{__counted_by attribute is here}} +// extra-note@+1 3{{__counted_by attribute is here}} +int* __counted_by(2) test_cb(int* __counted_by(3) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__counted_by attribute is here}} + // extra-note@+1 2{{__counted_by attribute is here}} + int* __counted_by(2) local_cb = p; + local_cb = p; // OK + side_effect(); + ++local_cb; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cb; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local_cb--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local_cb += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cb++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cb = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cb = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *local_cb-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local = local_cb + 1; // OK because `local_cb` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_cb++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cb; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cb--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + --global_cb; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cb -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cb++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cb = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cb-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *--global_cb = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb = global_cb + 1; // OK because `global_cb` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + consume_cb(++p); // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + struct cb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + S = (struct cb){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} +} + +// legacy-note@+3 1{{__counted_by attribute is here}} +// expected-note@+2 8{{__counted_by attribute is here}} +// extra-note@+1 3{{__counted_by attribute is here}} +int* __counted_by(2) test_cb_constant_fold_count(int* __counted_by(2+1) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__counted_by attribute is here}} + // extra-note@+1 2{{__counted_by attribute is here}} + int* __counted_by(1+1) local_cb = p; + local_cb = p; // OK + side_effect(); + ++local_cb; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cb; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local_cb--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local_cb += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cb++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cb = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cb = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *local_cb-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local = local_cb + 1; // OK because `local_cb` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_cb_opo++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cb_opo; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cb_opo--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + --global_cb_opo; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb_opo += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cb_opo -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cb_opo++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cb_opo = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cb_opo-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *--global_cb_opo = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb_opo = global_cb_opo + 1; // OK because `global_cb` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + consume_cb(++p); // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + struct cb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + S = (struct cb){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count of 3 always traps}} +} + +// legacy-note@+3 1{{__counted_by attribute is here}} +// expected-note@+2 8{{__counted_by attribute is here}} +// extra-note@+1 3{{__counted_by attribute is here}} +int* __counted_by(size) test_cb_const_qualified_size(const int size, int* __counted_by(size) p) { + int* local; + // Modify local var + const int local_size = 2; + // expected-note@+2 4{{__counted_by attribute is here}} + // extra-note@+1 2{{__counted_by attribute is here}} + int* __counted_by(local_size) local_cb = p; + side_effect(); + local_cb = p; // OK + + side_effect(); + ++local_cb; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cb; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local_cb--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + local_cb += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cb -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cb++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cb = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cb = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *local_cb-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + local = local_cb + 1; // OK because `local_cb` gets promoted to a __bidi_indexable first. + side_effect(); + + // Modify global + global_cb_const_qual_count++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cb_const_qual_count; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + --global_cb_const_qual_count; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb_const_qual_count += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cb_const_qual_count-= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cb_const_qual_count++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cb_const_qual_count = 1; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cb_const_qual_count-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *--global_cb_const_qual_count = 1; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + global_cb_const_qual_count = global_cb_const_qual_count + 1; // OK because `global_cb` gets promoted to a __bidi_indexable first. + + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by' pointer always traps}} + + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + + side_effect(); + + consume_cb(++p); // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + struct cb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by' pointer with side effects is not yet supported}} + S = (struct cb){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by' attributed pointer with constant count 'size' always traps}} +} + +// legacy-note@+3 1{{__counted_by_or_null attribute is here}} +// expected-note@+2 8{{__counted_by_or_null attribute is here}} +// extra-note@+1 3{{__counted_by_or_null attribute is here}} +int* __counted_by_or_null(2) test_cbon(int* __counted_by_or_null(3) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__counted_by_or_null attribute is here}} + // extra-note@+1 2{{__counted_by_or_null attribute is here}} + int* __counted_by_or_null(2) local_cbon = p; + local_cbon = p; // OK + side_effect(); + ++local_cbon; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cbon; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local_cbon--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local_cbon += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cbon++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cbon = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cbon = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *local_cbon-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local = local_cbon + 1; // OK because `local_cbon` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_cbon++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cbon; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cbon--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + --global_cbon; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cbon -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cbon++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cbon = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cbon-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *--global_cbon = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon = global_cbon + 1; // OK because `global_cbon` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + consume_cbon(++p); // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + struct cbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + S = (struct cbon){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} +} + +// legacy-note@+3 1{{__counted_by_or_null attribute is here}} +// expected-note@+2 8{{__counted_by_or_null attribute is here}} +// extra-note@+1 3{{__counted_by_or_null attribute is here}} +int* __counted_by_or_null(2) test_cbon_constant_fold_count(int* __counted_by_or_null(2+1) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__counted_by_or_null attribute is here}} + // extra-note@+1 2{{__counted_by_or_null attribute is here}} + int* __counted_by_or_null(1+1) local_cbon = p; + local_cbon = p; // OK + side_effect(); + ++local_cbon; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cbon; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local_cbon--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local_cbon += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cbon++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cbon = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cbon = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *local_cbon-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local = local_cbon + 1; // OK because `local_cbon` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_cbon_opo++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cbon_opo; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cbon_opo--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + --global_cbon_opo; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon_opo += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cbon_opo -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cbon_opo++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cbon_opo = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cbon_opo-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *--global_cbon_opo = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon_opo = global_cbon_opo + 1; // OK because `global_cbon` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + consume_cbon(++p); // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + struct cbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + S = (struct cbon){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 3 always traps}} +} + +// legacy-note@+3 1{{__counted_by_or_null attribute is here}} +// expected-note@+2 8{{__counted_by_or_null attribute is here}} +// extra-note@+1 3{{__counted_by_or_null attribute is here}} +int* __counted_by_or_null(size) test_cbon_const_qualified_size(const int size, int* __counted_by_or_null(size) p) { + int* local; + // Modify local var + const int local_size = 2; + // expected-note@+2 4{{__counted_by_or_null attribute is here}} + // extra-note@+1 2{{__counted_by_or_null attribute is here}} + int* __counted_by_or_null(local_size) local_cbon = p; + side_effect(); + local_cbon = p; // OK + + side_effect(); + ++local_cbon; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + --local_cbon; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local_cbon--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + local_cbon += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + local_cbon -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_cbon++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++local_cbon = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *--local_cbon = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *local_cbon-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + local = local_cbon + 1; // OK because `local_cbon` gets promoted to a __bidi_indexable first. + side_effect(); + + // Modify global + global_cbon_const_qual_count++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + ++global_cbon_const_qual_count; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + --global_cbon_const_qual_count; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon_const_qual_count += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + global_cbon_const_qual_count-= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_cbon_const_qual_count++ = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + *++global_cbon_const_qual_count = 1; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count of 2 always traps}} + side_effect(); + + *global_cbon_const_qual_count-- = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *--global_cbon_const_qual_count = 1; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + global_cbon_const_qual_count = global_cbon_const_qual_count + 1; // OK because `global_cbon` gets promoted to a __bidi_indexable first. + + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__counted_by_or_null' pointer always traps}} + + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + + side_effect(); + + consume_cbon(++p); // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + struct cbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + }; + // cli-error@+1{{initalizer for '__counted_by_or_null' pointer with side effects is not yet supported}} + S = (struct cbon){.buf = p++}; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__counted_by_or_null' attributed pointer with constant count 'size' always traps}} +} + +// Warning diagnostic tests + +void downgrade_to_warning(int* __counted_by(4) ptr) { // expected-note{{__counted_by attribute is here}} +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wbounds-safety-externally-counted-ptr-arith-constant-count" + ++ptr; // expected-warning{{positive pointer arithmetic on '__counted_by' attributed pointer with constant count of 4 always traps}} +#pragma clang diagnostic pop +} + +void downgrade_to_ignored(int* __counted_by(4) ptr) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wbounds-safety-externally-counted-ptr-arith-constant-count" + ++ptr; // ok +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/counted_by_type_incomplete_completable_struct.c b/clang/test/BoundsSafety-legacy-checks/Sema/counted_by_type_incomplete_completable_struct.c new file mode 100644 index 0000000000000..4076f36f1f48b --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/counted_by_type_incomplete_completable_struct.c @@ -0,0 +1,1444 @@ + +// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +#include +// Test diagnostics on _counted_by(_or_null) pointers with an incomplete struct +// pointee type. + +// NOTE: For a typedef the source location is of the underlying type instead of +// the typedef. This seems like the right behavior because the typedef isn't the +// forward declaration, `struct IncompleteStructTy` is. +// +// expected-note@+1 62{{consider providing a complete definition for 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy')}} +struct IncompleteStructTy; // expected-note 153{{consider providing a complete definition for 'struct IncompleteStructTy'}} + +typedef struct IncompleteStructTy Incomplete_Struct_t; + +//------------------------------------------------------------------------------ +// Attribute on parameters +//------------------------------------------------------------------------------ + +// On declarations its ok to use the attribute +void no_consume_ok( + struct IncompleteStructTy* __counted_by(size) cb, + struct IncompleteStructTy* __counted_by_or_null(size) cbon, + int size); // OK + +// Using the attribute on parameters on a function **definition** is not allowed. +void no_consume_ok( + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size) cb, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size) cbon, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int size) { + +} + +void no_consume_ok_unnamed_param( + struct IncompleteStructTy* __counted_by(size), + struct IncompleteStructTy* __counted_by_or_null(size), + int size); // OK + +void no_consume_ok_unnamed_param( + // expected-error@+2{{cannot apply '__counted_by' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} + struct IncompleteStructTy* __counted_by(size), // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+2{{cannot apply '__counted_by_or_null' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} + struct IncompleteStructTy* __counted_by_or_null(size), // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int size) { + +} + +void consume_cb(struct IncompleteStructTy* __counted_by(size_cb), int size_cb); +void consume_cbon(struct IncompleteStructTy* __counted_by_or_null(size_cbon), int size_cbon); + +void consume_param_read_write( + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size_cb)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size_cb) cb, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size_cbon)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size_cbon) cbon, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int size_cb, + int size_cbon) { + + // There shouldn't be diagnostics on the uses because the parameters are marked + // as invalid. + + // Read + struct IncompleteStructTy* local = cb; + local = cb; + local =&cb[1]; + consume_cb(cb); + + // Write + cb = 0x0; + // TODO: This diagnostic should not be firing. rdar://133001202 + // expected-error@+1{{assignment to 'size_cb' requires corresponding assignment to 'struct IncompleteStructTy *__single __counted_by(size_cb)' (aka 'struct IncompleteStructTy *__single') 'cb'; add self assignment 'cb = cb' if the value has not changed}} + size_cb = 0; + + + // Read + struct IncompleteStructTy* local2 = cbon; + local2 = cbon; + local2 =&cbon[1]; + consume_cbon(cbon); + + // Write + cbon = 0x0; + // TODO: This diagnostic should not be firing. rdar://133001202 + // expected-error@+1{{assignment to 'size_cbon' requires corresponding assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(size_cbon)' (aka 'struct IncompleteStructTy *__single') 'cbon'; add self assignment 'cbon = cbon' if the value has not changed}} + size_cbon = 0; +} + +// These errors seem prevent emitting any further diagnostics about the attributes. +void no_consume_default_assign( + // expected-error@+1{{C does not support default arguments}} + struct IncompleteStructTy* __counted_by(size) cb = 0x0, + // expected-error@+1{{C does not support default arguments}} + struct IncompleteStructTy* __counted_by_or_null(size) cbon = 0x0, + int size) { + +} + +//------------------------------------------------------------------------------ +// Attribute on parameters with nested attributes +//------------------------------------------------------------------------------ +void consume_param_nested( + struct IncompleteStructTy* __counted_by(size1)* cb, // expected-note 3{{consider using '__sized_by' instead of '__counted_by'}} + struct IncompleteStructTy* __counted_by_or_null(size2)* cbon, // expected-note 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int size1, int size2) { + + // Surprisingly `&cb[0]` doesn't count as a use. + struct IncompleteStructTy** local = &cb[0]; + + // expected-error@+1{{pointer with '__counted_by' cannot be pointed to by any other variable; exception is when the variable is passed as a compatible argument to a function}} + local = cb; + + // expected-error@+1{{cannot assign to object with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + *cb = 0x0; + size1 = 0; + + // expected-error@+1{{cannot use 'cb[0]' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + void* read_cb = cb[0]; + // expected-error@+1{{cannot use '*cb' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_cb(*cb, size1); + + // expected-error@+1{{not allowed to change out parameter with dependent count}} + cb = 0x0; + + // Surprisingly `&cbon[0]` doesn't count as a use. + struct IncompleteStructTy** local2 = &cbon[0]; + // expected-error@+1{{pointer with '__counted_by_or_null' cannot be pointed to by any other variable; exception is when the variable is passed as a compatible argument to a function}} + local = cbon; + + // expected-error@+1{{cannot assign to object with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + *cbon = 0x0; + size2 = 0; + + // expected-error@+1{{cannot use 'cbon[0]' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + void* read_cbon = cbon[0]; + // expected-error@+1{{cannot use '*cbon' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_cbon(*cbon, size2); + + // expected-error@+1{{not allowed to change out parameter with dependent count}} + cbon = 0x0; +} + +//------------------------------------------------------------------------------ +// Attribute on return type of called function +//------------------------------------------------------------------------------ + +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteStructTy* __counted_by(size) ret_cb_IncompleteStructTy(int size); // OK +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} +Incomplete_Struct_t* __counted_by(size) ret_cb_IncompleteStructTy_typedef(int size); // OK +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +struct IncompleteStructTy* __counted_by_or_null(size) ret_cbon_IncompleteStructTy(int size); // OK +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +Incomplete_Struct_t* __counted_by_or_null(size) ret_cbon_IncompleteStructTy_typedef(int size); // OK + +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteStructTy* __counted_by(1) ret_cb_IncompleteStructTy_const_count_one(void); // OK +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} +Incomplete_Struct_t* __counted_by(1) ret_cb_IncompleteStructTy_typedef_const_count_one(void); // OK +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +struct IncompleteStructTy* __counted_by_or_null(1) ret_cbon_IncompleteStructTy_const_count_one(void); // OK +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +Incomplete_Struct_t* __counted_by_or_null(1) ret_cbon_IncompleteStructTy_typedef_const_count_one(void); // OK + +void call_fn_returns_incomplete_pointee(void) { + int size = 0; + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy' with '__counted_by' attributed return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + ret_cb_IncompleteStructTy(size); + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef' with '__counted_by' attributed return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + ret_cb_IncompleteStructTy_typedef(size); + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy' with '__counted_by_or_null' attributed return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + ret_cbon_IncompleteStructTy(size); + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef' with '__counted_by_or_null' attributed return type 'Incomplete_Struct_t *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + ret_cbon_IncompleteStructTy_typedef(size); + + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_const_count_one' with '__counted_by' attributed return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + ret_cb_IncompleteStructTy_const_count_one(); + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef_const_count_one' with '__counted_by' attributed return type 'Incomplete_Struct_t *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + ret_cb_IncompleteStructTy_typedef_const_count_one(); + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_const_count_one' with '__counted_by_or_null' attributed return type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + ret_cbon_IncompleteStructTy_const_count_one(); + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef_const_count_one' with '__counted_by_or_null' attributed return type 'Incomplete_Struct_t *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + ret_cbon_IncompleteStructTy_typedef_const_count_one(); +} + +//------------------------------------------------------------------------------ +// Attribute on return type in function declaration +//------------------------------------------------------------------------------ + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb(int size) { + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_missing_return(int size) { + // missing return statement +} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + consume_param_and_return_cbon_missing_return(int size) { + // missing return statement +} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 3{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_multiple_returns(int size) { + if (size == 0) + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; + + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + consume_param_and_return_cbon_multiple_returns(int size) { + if (size == 0) + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; + + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(1) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_const_count_1(int size) { + // rs-error@+2{{returning null from a function with result type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 always fails}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} +consume_param_and_return_cb_single_forge(int size) { + // rs-warning@+2{{count value is not statically known: returning 'struct IncompleteStructTy *__single' from a function with result type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') is invalid for any count other than 0 or 1}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return __unsafe_forge_single(struct IncompleteStructTy*, 0x0); +} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_single_forge_bidi(int size) { + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x0, 4); +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + consume_param_and_return_cbon(int size) { + // TODO: We should consider allowing this because the assignment of nullptr + // means the type size isn't needed (rdar://129424354). + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +consume_param_and_return_cbon_single_forge(int size) { + // rs-warning@+2{{count value is not statically known: returning 'struct IncompleteStructTy *__single' from a function with result type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') is invalid for any count other than 0 or 1 unless the pointer is null}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return __unsafe_forge_single(struct IncompleteStructTy*, 0x0); +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + consume_param_and_return_cbon_single_forge_bidi(int size) { + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x0, 4); +} + +// Test typedef as the incomplete pointee type +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_typedef(int size) { + // expected-error@+1{{cannot return '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + return 0x0; +} + +// Check Incomplete type diagnostic and bad conversion diagnostics both emitted on return + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + consume_param_and_return_cb_bad_conversion(int size) { + // expected-error@+2{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{non-pointer to safe pointer conversion is not allowed with -fbounds-safety; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable'}} + return 0x1; +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + consume_param_and_return_cbon_bad_conversion(int size) { + // expected-error@+2{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{non-pointer to safe pointer conversion is not allowed with -fbounds-safety; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable'}} + return 0x1; +} + +//------------------------------------------------------------------------------ +// Pass Arguments to parameters with attribute. +//------------------------------------------------------------------------------ +void consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_incomplete_cb_unnamed(struct IncompleteStructTy* __counted_by(size), int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +typedef void consume_incomplete_cb_t(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +void call_consume_incomplete_cb(consume_incomplete_cb_t indirect_call) { + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb_unnamed(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); + + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); +} + +void consume_incomplete_cb_const_count_1(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_incomplete_cb_unnamed_const_count_1(struct IncompleteStructTy* __counted_by(1)); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +typedef void consume_incomplete_cb_const_count_1_t(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + + +void call_consume_incomplete_cb_const_count_1(consume_incomplete_cb_const_count_1_t indirect_call) { + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb_const_count_1(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb_unnamed_const_count_1(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); + + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); +} + +void consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +void consume_incomplete_cbon_unnamed(struct IncompleteStructTy* __counted_by_or_null(size), int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +typedef void consume_incomplete_cbon_t(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +void call_consume_incomplete_cbon(consume_incomplete_cbon_t indirect_call) { + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cbon(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); + // expected-error@+1{{cannot pass argument to parameter with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cbon_unnamed(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); + + // expected-error@+1{{cannot pass argument to parameter with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); +} + + +// expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +void wrap_consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + int size, consume_incomplete_cb_t indirect_call) { + // TODO: We should consider allowing this case. rdar://132031085 + // + // This case technically doesn't require any bounds-checks because: + // + // 1. We assume the attribute on `c` is correct because we assume that the + // caller to `wrap_consume_incomplete_cb` already performed bounds-checks. + // 2. uses of `c` and `size` in this function just pass them along to + // functions with the same kind of count expression. This means the bounds + // checks performed at the call to `wrap_consume_incomplete_cb` being true + // imply that all the bounds checks that would be performed here should + // pass. One exception to this would be if the call to + // `wrap_consume_incomplete_cb` was performed from non-bounds-safety code. + // + consume_incomplete_cb(c, size); + consume_incomplete_cb_unnamed(c, size); + indirect_call(c, size); +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +void wrap_consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int size, consume_incomplete_cbon_t indirect_call) { + // TODO: We should consider allowing this case. rdar://132031085 + // + // This case technically doesn't require any bounds-checks because: + // + // 1. We assume the attribute on `c` is correct because we assume that the + // caller to `wrap_consume_incomplete_cb` already performed bounds-checks. + // 2. uses of `c` and `size` in this function just pass them along to + // functions with the same kind of count expression. This means the bounds + // checks performed at the call to `wrap_consume_incomplete_cb` being true + // imply that all the bounds checks that would be performed here should + // pass. One exception to this would be if the call to + // `wrap_consume_incomplete_cb` was performed from non-bounds-safety code. + // + consume_incomplete_cbon(c, size); + consume_incomplete_cbon_unnamed(c, size); + indirect_call(c, size); +} + +//------------------------------------------------------------------------------ +// Passing to Parameters with attributes on nested pointer +//------------------------------------------------------------------------------ +void consume_incomplete_cb_nested(struct IncompleteStructTy* __counted_by(*size)* out, int* size); +void consume_incomplete_cb_unnamed_nested(struct IncompleteStructTy* __counted_by(*size)*, int* size); +typedef void consume_incomplete_cb_nested_t(struct IncompleteStructTy* __counted_by(*size)* c, int* size); + +struct PtrAndCountCB { + int size; + struct IncompleteStructTy* __counted_by(size) ptr; +}; + +extern int cb_global_count; +extern struct IncompleteStructTy* __counted_by(cb_global_count) cb_global; + +void call_consume_incomplete_cb_nested(consume_incomplete_cb_nested_t indirect_call, struct PtrAndCountCB* ptr_and_count) { + // Note: + // * Uses of `&cb_global` `&(ptr_and_count->ptr)` currently don't generate errors + // because only the outer most + // pointer is checked. + // * Calls to the functions don't generate errors because only the outer most + // pointer is checked in the parameter types. + // + // This is ok because currently we don't checks at call sites to functions + // with indirect __counted_by parameters. Therefore the size of + // `struct IncompleteStructTy` isn't needed. + consume_incomplete_cb_nested(&cb_global, &cb_global_count); + consume_incomplete_cb_unnamed_nested(&cb_global, &cb_global_count); + indirect_call(&cb_global, &cb_global_count); + consume_incomplete_cb_nested(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK + consume_incomplete_cb_unnamed_nested(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK + indirect_call(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK +} + +void consume_incomplete_cbon_nested(struct IncompleteStructTy* __counted_by_or_null(*size)* out, int* size); +void consume_incomplete_cbon_unnamed_nested(struct IncompleteStructTy* __counted_by_or_null(*size)*, int* size); +typedef void consume_incomplete_cbon_nested_t(struct IncompleteStructTy* __counted_by_or_null(*size)* c, int* size); + +extern int cbon_global_count; +extern struct IncompleteStructTy* __counted_by_or_null(cbon_global_count) cbon_global; + +struct PtrAndCountCBON { + int size; + struct IncompleteStructTy* __counted_by_or_null(size) ptr; +}; + +void call_consume_incomplete_cbon_nested(consume_incomplete_cbon_nested_t indirect_call, struct PtrAndCountCBON* ptr_and_count) { + // Note: + // * Uses of `&cbon_global` `&(ptr_and_count->ptr)` currently don't generate errors + // because only the outer most + // pointer is checked. + // * Calls to the functions don't generate errors because only the outer most + // pointer is checked in the parameter types. + // + // This is ok because currently we don't checks at call sites to functions + // with indirect __counted_by parameters. Therefore the size of + // `struct IncompleteStructTy` isn't needed. + consume_incomplete_cbon_nested(&cbon_global, &cbon_global_count); + consume_incomplete_cbon_unnamed_nested(&cbon_global, &cbon_global_count); + indirect_call(&cbon_global, &cbon_global_count); + consume_incomplete_cbon_nested(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK + consume_incomplete_cbon_unnamed_nested(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK + indirect_call(&(ptr_and_count->ptr), &(ptr_and_count->size)); // OK +} + +//------------------------------------------------------------------------------ +// __counted_by/__counted_by_or_null on struct members +//------------------------------------------------------------------------------ + +struct BuffersCBTyNotUsed { + int count; + struct IncompleteStructTy* __counted_by(count) buffer; // OK + Incomplete_Struct_t* __counted_by(count) buffer_typedef; // OK +}; +struct BuffersCBTy { + int count; + int count_typedef; + struct IncompleteStructTy* __counted_by(count) buffer; // expected-note 21{{consider using '__sized_by' instead of '__counted_by'}} + Incomplete_Struct_t* __counted_by(count_typedef) buffer_typedef; // expected-note 21{{consider using '__sized_by' instead of '__counted_by'}} +}; + +void side_effect(void); + +void AssignToBuffersCBTy(struct BuffersCBTy* b) { + // Check that the diagnostic about missing assignment to the count also shows + + // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') 'b->buffer' requires corresponding assignment to 'b->count'; add self assignment 'b->count = b->count' if the value has not changed}} + b->buffer = 0x0; + side_effect(); + // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + // expected-error@+1{{assignment to 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') 'b->buffer_typedef' requires corresponding assignment to 'b->count_typedef'; add self assignment 'b->count_typedef = b->count_typedef' if the value has not changed}} + b->buffer_typedef = 0x0; + + // Diagnostic about missing assignment to count should not appear. + side_effect(); + b->count = 0; + // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + b->buffer = 0x0; + side_effect(); + // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + b->buffer_typedef = 0x0; + b->count_typedef = 0; +} + + +struct IncompleteStructTy* ReturnBufferCBTyMember(struct BuffersCBTy* b) { + // expected-error@+1{{cannot use 'b->buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return b->buffer; +} + +Incomplete_Struct_t* ReturnBufferCBTyMemberTypeDef(struct BuffersCBTy* b) { + // expected-error@+1{{cannot use 'b->buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + return b->buffer_typedef; +} + +struct BuffersCBONTyNotUsed { + int count; + struct IncompleteStructTy* __counted_by_or_null(count) buffer; // OK + Incomplete_Struct_t* __counted_by_or_null(count) buffer_typedef; // OK +}; +struct BuffersCBONTy { + int count; + int count_typedef; + struct IncompleteStructTy* __counted_by_or_null(count) buffer; // expected-note 21{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + Incomplete_Struct_t* __counted_by_or_null(count_typedef) buffer_typedef; // expected-note 21{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void AssignToBuffersCBONTy(struct BuffersCBONTy* b) { + // Check that the diagnostic about missing assignment to the count also shows + + // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') 'b->buffer' requires corresponding assignment to 'b->count'; add self assignment 'b->count = b->count' if the value has not changed}} + b->buffer = 0x0; + side_effect(); + // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + // expected-error@+1{{assignment to 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') 'b->buffer_typedef' requires corresponding assignment to 'b->count_typedef'; add self assignment 'b->count_typedef = b->count_typedef' if the value has not changed}} + b->buffer_typedef = 0x0; + + // Diagnostic about missing assignment to count should not appear. + side_effect(); + b->count = 0; + // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + b->buffer = 0x0; + side_effect(); + // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + b->buffer_typedef = 0x0; + b->count_typedef = 0; +} + +struct IncompleteStructTy* ReturnBufferCBONTyMember(struct BuffersCBONTy* b) { + // expected-error@+1{{cannot use 'b->buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + return b->buffer; +} + +Incomplete_Struct_t* ReturnBufferCBONTyMemberTypeDef(struct BuffersCBONTy* b) { + // expected-error@+1{{cannot use 'b->buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + return b->buffer_typedef; +} + +//------------------------------------------------------------------------------ +// Initialization of struct members with counted_by/counted_by_or_null +//------------------------------------------------------------------------------ + +// TODO: We should consider allowing implicit and explicit zero initialization +// of __counted_by_or_null pointers. rdar://129424354 + +struct BufferCBNonZeroConstCountTy { + int extra_field; + struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 4{{consider using '__sized_by' instead of '__counted_by'}} +}; + +struct BufferCBNonZeroConstCountFlippedFieldOrderTy { + struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + int extra_field; +}; + +struct BufferCBNonZeroDynCountTy { + unsigned int count; + struct IncompleteStructTy* __counted_by(count+1) ptr; // expected-note 5{{consider using '__sized_by' instead of '__counted_by'}} +}; + +union BufferCBOrOther { + struct BuffersCBTy buf; + int other; +}; + +void InitBuffersCBTy(int size) { + // Designated initializers + struct BuffersCBTy desig_init_0 = { + .count = size, + .count_typedef = size, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0x0 + }; + + struct BuffersCBTy desig_init_1 = { + // .count and .count_typedef not explicitly initialized but are implicitly zero initialized + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0x0 + }; + + struct BuffersCBTy desig_init_partial = { + .count = size, + .count_typedef = size, + // .buffer and .buffer_typedef are not explicit initialized but are implicitly zero initialized + }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + struct BuffersCBTy implicit_all_zero_init = {0}; // Implicit field init + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // non-designated initializer + struct BuffersCBTy non_design_init_0 = { + 0, + 0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0x0 + }; + + struct BuffersCBTy non_design_init_1 = { 0, 0 }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + struct BuffersCBTy desig_init_invalid_count = { + .count = 1, + // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'desig_init_invalid_count.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + .buffer = 0x0 + }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + struct BuffersCBTy desig_init_invalid_count_partial = { + .count = 1 + }; + // expected-error@-1{{implicitly initializing 'desig_init_invalid_count_partial.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + struct BuffersCBTy non_desig_init_invalid_count = { + 1, + 0, + // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'non_desig_init_invalid_count.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0x0 + }; + + + struct BuffersCBTy non_desig_init_invalid_count_partial = {1}; + // expected-error@-1{{implicitly initializing 'non_desig_init_invalid_count_partial.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // Cases where zero-init would create an invalid count + struct BufferCBNonZeroConstCountTy design_init_const_count = { + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'design_init_const_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + .ptr = 0x0, + .extra_field = 0 + }; + + struct BufferCBNonZeroConstCountTy design_init_const_count_partial_explicit = { + // .ptr is implicitly zero initialized + .extra_field = 0x0 + }; + // expected-error@-1{{implicitly initializing 'design_init_const_count_partial_explicit.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + struct BufferCBNonZeroConstCountTy implicit_all_zero_init_const_count = {0}; + // expected-error@-1{{implicitly initializing 'implicit_all_zero_init_const_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + // When the ptr comes first it's seen as an explicit assignment when we write ` = {0}` so we get the incomplete pointee type error diagnostic + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'implicit_all_zero_init_const_count_ptr_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + struct BufferCBNonZeroConstCountFlippedFieldOrderTy implicit_all_zero_init_const_count_ptr_init = {0}; + + struct BufferCBNonZeroDynCountTy design_init_non_zero_dyn_count = { + .count = 0x0, + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'design_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + .ptr = 0x0 + }; + + struct BufferCBNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init = { + // count is implicitly zero + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'design_init_non_zero_dyn_count_partial_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + .ptr = 0x0 + }; + + struct BufferCBNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init2 = { + // ptr is implicitly zero initialized + .count = 0x0 + }; + // expected-error@-1{{implicitly initializing 'design_init_non_zero_dyn_count_partial_init2.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + struct BufferCBNonZeroDynCountTy implicit_all_zero_init_non_zero_dyn_count = {0}; + // expected-error@-1{{implicitly initializing 'implicit_all_zero_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + struct BufferCBNonZeroDynCountTy non_desig_init_non_zero_dyn_count = { + 0, + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'non_desig_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + 0 + }; + + // Struct inside a union + union BufferCBOrOther UnionDesignInitOther = {.other = 0x0 }; + union BufferCBOrOther UnionZeroInit = {0}; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + union BufferCBOrOther UnionDesignInitBufZeroInitStructFields = {.buf = {0}}; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + union BufferCBOrOther UnionDesignInitBufDesignInitStructFields = {.buf = {.count = 0, .buffer = 0x0}}; + // expected-error@-1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +} + +struct BuffersCBTy GlobalBuffersCBTy_design_init = { + .count = 0, + .count_typedef = 0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0 +}; + +struct BuffersCBTy GlobalBuffersCBTy_non_design_init = { + 0, + 0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + 0, + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0 +}; + +struct BuffersCBTy GlobalBuffersCBTy_design_init_partial = { + .count = 0, + .count_typedef = 0 + // buffer and buffer_typedef are implicitly zero initialized +}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + +struct BuffersCBTy GlobalBuffersCBTy_non_design_init_partial = { + 0, + 0, + // buffer and buffer_typedef are implicitly zero initialized +}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + +struct BuffersCBTy GlobalBuffersCBTy_all_zero_init = {0}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + +// expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@+1{{initializing 'GlobalBuffersCBTy_implicit_all_zero_init_const_count_ptr_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} +struct BufferCBNonZeroConstCountFlippedFieldOrderTy GlobalBuffersCBTy_implicit_all_zero_init_const_count_ptr_init = {0}; + +struct BufferCBNonZeroConstCountTy GlobalBuffersCBTy_const_non_zero_count = { + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'GlobalBuffersCBTy_const_non_zero_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} + .ptr = 0x0 +}; + +// counted_by_or_null variants + + +union BufferCBONOrOther { + struct BuffersCBONTy buf; + int other; +}; + +struct BufferCBONNonZeroConstCountTy { + int extra_field; + struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 4{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +struct BufferCBONNonZeroConstCountFlippedFieldOrderTy { + struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + int extra_field; +}; + +struct BufferCBONNonZeroDynCountTy { + unsigned int count; + struct IncompleteStructTy* __counted_by_or_null(count+1) ptr; // expected-note 5{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void InitBuffersCBONTy(int size) { + // Designated initializers + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy desig_init_0 = { + .count = size, + .count_typedef = size, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0x0 + }; + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy desig_init_1 = { + // .count and .count_typedef not explicitly initialized but are implicitly zero initialized + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0x0 + }; + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy desig_init_partial = { + .count = size, + .count_typedef = size, + // .buffer and .buffer_typedef are not explicit initialized but are implicitly zero initialized + }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy implicit_all_zero_init = {0}; // Implicit field init + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // non-designated initializer + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy non_design_init_0 = { + 0, + 0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0x0 + }; + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy non_design_init_1 = { 0, 0 }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // TODO: Explicit and implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy desig_init_invalid_count = { + .count = 1, + // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + .buffer = 0x0 + }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy desig_init_explicit_non_zero_count_partial = { + .count = 1 + }; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy non_desig_init_invalid_count = { + 1, + 0, + // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0x0 + }; + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BuffersCBONTy non_desig_init_non_zerocount_partial = {1}; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + // Cases where zero-init would create an invalid count + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroConstCountTy design_init_const_count = { + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + .ptr = 0x0, + .extra_field = 0 + }; + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroConstCountTy design_init_const_count_partial_explicit = { + // .ptr is implicitly zero initialized + .extra_field = 0x0 + }; + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroConstCountTy implicit_all_zero_init_const_count = {0}; + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + // When the ptr comes first it's seen as an explicit assignment when we write ` = {0}` so we get the incomplete pointee type error diagnostic + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + struct BufferCBONNonZeroConstCountFlippedFieldOrderTy implicit_all_zero_init_const_count_ptr_init = {0}; + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroDynCountTy design_init_non_zero_dyn_count = { + .count = 0x0, + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + .ptr = 0x0 + }; + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init = { + // count is implicitly zero + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + .ptr = 0x0 + }; + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init2 = { + // ptr is implicitly zero initialized + .count = 0x0 + }; + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroDynCountTy implicit_all_zero_init_non_zero_dyn_count = {0}; + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + + // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 + struct BufferCBONNonZeroDynCountTy non_desig_init_non_zero_dyn_count = { + 0, + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + 0 + }; + + // Struct inside a union + union BufferCBONOrOther UnionDesignInitOther = {.other = 0x0 }; + union BufferCBONOrOther UnionZeroInit = {0}; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + union BufferCBONOrOther UnionDesignInitBufZeroInitStructFields = {.buf = {0}}; + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + union BufferCBONOrOther UnionDesignInitBufDesignInitStructFields = {.buf = {.count = 0, .buffer = 0x0}}; + // expected-error@-1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +} + +// XXX + +struct BuffersCBONTy GlobalBuffersCBONTy_design_init = { + .count = 0, + .count_typedef = 0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + .buffer = 0x0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + .buffer_typedef = 0 +}; + +struct BuffersCBONTy GlobalBuffersCBONTy_non_design_init = { + 0, + 0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + 0, + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + 0 +}; + +struct BuffersCBONTy GlobalBuffersCBONTy_design_init_partial = { + .count = 0, + .count_typedef = 0 + // buffer and buffer_typedef are implicitly zero initialized +}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + +struct BuffersCBONTy GlobalBuffersCBONTy_non_design_init_partial = { + 0, + 0, + // buffer and buffer_typedef are implicitly zero initialized +}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + +struct BuffersCBONTy GlobalBuffersCBONTy_all_zero_init = {0}; +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} + + +// expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// +struct BufferCBONNonZeroConstCountFlippedFieldOrderTy GlobalBuffersCBONTy_implicit_all_zero_init_const_count_ptr_init = {0}; + +struct BufferCBONNonZeroConstCountTy GlobalBuffersCBONTy_const_non_zero_count = { + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // + .ptr = 0x0 +}; + +//------------------------------------------------------------------------------ +// Local __counted_by variables +//------------------------------------------------------------------------------ +void local_cb_init_and_assign(int s) { + int size = s; + + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size) local_init = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + local_init = 0x0; + + int implicit_size = s; + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(implicit_size) implicit_init; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + implicit_init = 0x0; +} + +void local_cb_init_and_assign_constant_count(void) { + // Check we also emit diagnostics about assigning nullptr to `__counted_by(X)` where X > 0 + // + // expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{initializing 'local_init' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} + struct IncompleteStructTy* __counted_by(5) local_init = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + local_init = 0x0; // Diagnostic suppressed because the VarDecl is invalid + + // There should be no diagnostic about assigning nullptr + // TODO: We should consider allowing this given that the type size isn't + // really needed when the count is 0 (rdar://129424147). + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(0) local_init_zero = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + local_init_zero = 0x0; // Diagnostic suppressed because the VarDecl is invalid + + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // Diagnostic suppressed because the VarDecl is invalid +} + +void local_cbon_init_and_assign(int s) { + int size = s; + + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size) local_init = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + local_init = 0x0; + + int implicit_size = s; + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(implicit_size) implicit_init; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + implicit_init = 0x0; +} + +void local_cbon_init_and_assign_constant_count(void) { + // TODO: We should consider allowing this because the assignment of nullptr + // means the type size isn't needed (rdar://129424354). + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(5) local_init = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + local_init = 0x0; // Diagnostic suppressed because the VarDecl is invalid + + // There should be no diagnostic about assigning nullptr + // TODO: We should consider allowing this given that the type size isn't + // really needed when the count is 0 (rdar://129424147). + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(0) local_init_zero = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + local_init_zero = 0x0; // Diagnostic suppressed because the VarDecl is invalid + + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // Diagnostic suppressed because the VarDecl is invalid +} + +//------------------------------------------------------------------------------ +// Global __counted_by variables +//------------------------------------------------------------------------------ +// NOTE: Tentative definitions are mostly tested in `counted_by_type_incomplete_completable_struct_tentative_defs.c`. + +extern int external_count; +// expected-note@+1 3{{consider using '__sized_by' instead of '__counted_by'}} +extern struct IncompleteStructTy* __counted_by(external_count) GlobalCBPtrToIncompleteTy; // OK +extern Incomplete_Struct_t* __counted_by(external_count) GlobalCBPtrToIncompleteTyTypeDef; // OK + +void use_GlobalCBPtrToIncompleteTy(void) { + // expected-error@+2{{cannot assign to 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBPtrToIncompleteTy' requires corresponding assignment to 'external_count'; add self assignment 'external_count = external_count' if the value has not changed}} + GlobalCBPtrToIncompleteTy = 0x0; + // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + GlobalCBPtrToIncompleteTy[0] = 0; + // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb(GlobalCBPtrToIncompleteTy, external_count); +} + +static int global_count; +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +static struct IncompleteStructTy* __counted_by(global_count) GlobalCBPtrImplicitInit; // expected-note 4{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +static Incomplete_Struct_t* __counted_by(global_count) GlobalCBPtrImplicitInitTypeDef; // expected-note {{consider using '__sized_by' instead of '__counted_by'}} + +void use_GlobalCBPtrImplicitInit(void) { + // expected-error@+2{{cannot assign to 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBPtrImplicitInit' requires corresponding assignment to 'global_count'; add self assignment 'global_count = global_count' if the value has not changed}} + GlobalCBPtrImplicitInit = 0x0; + // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + GlobalCBPtrImplicitInit[0] = 0; + // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cb(GlobalCBPtrImplicitInit, global_count); +} + +int global_count_non_static = 0; +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(global_count_non_static) GlobalCBPtrExplicitInit = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(global_count_non_static) GlobalCBPtrExplicitInitTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +void use_GlobalCBPtrExplicitInit(void) { + // No diagnostics because the VarDecl is marked as invalid at this point + GlobalCBPtrExplicitInit = 0x0; + GlobalCBPtrExplicitInit[0] = 0; + consume_incomplete_cb(GlobalCBPtrExplicitInit, global_count_non_static); +} + +// This is very unidiomatic C but it seems to be legal. +// expected-warning@+1{{'extern' variable has an initializer}} +extern int global_count_extern = 0; +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 +extern struct IncompleteStructTy* __counted_by(global_count_extern) GlobalCBPtrExplicitInitExtern = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +// expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 +extern Incomplete_Struct_t* __counted_by(global_count_extern) GlobalCBPtrExplicitInitTypeDefExtern = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +// TODO: We should consider allowing this given that the pointee type size isn't +// really needed when the count is 0 (rdar://129424147) +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCount; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCountTypeDef; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCount = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@+1{{implicitly initializing 'GlobalCBPtrImplicitInitConstantNonZeroCount' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} +struct IncompleteStructTy* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCount; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +// expected-error@+1{{implicitly initializing 'GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef' of type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} +Incomplete_Struct_t* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@+1{{initializing 'GlobalCBPtrExplicitInitConstantNonZeroCount' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} +struct IncompleteStructTy* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCount = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +// expected-error@+1{{initializing 'GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef' of type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} +Incomplete_Struct_t* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +//------------------------------------------------------------------------------ +// Global __counted_by_or_null variables +//------------------------------------------------------------------------------ +// NOTE: Tentative definitions are mostly tested in `counted_by_type_incomplete_completable_struct_tentative_defs.c`. + +extern int external_count_cbon; +extern int external_count_cbon_typedef; +// expected-note@+1 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +extern struct IncompleteStructTy* __counted_by_or_null(external_count_cbon) GlobalCBONPtrToIncompleteTy; // OK +extern Incomplete_Struct_t* __counted_by_or_null(external_count_cbon_typedef) GlobalCBONPtrToIncompleteTyTypeDef; // OK + +void use_GlobalCBONPtrToIncompleteTy(void) { + // expected-error@+2{{cannot assign to 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBONPtrToIncompleteTy' requires corresponding assignment to 'external_count_cbon'; add self assignment 'external_count_cbon = external_count_cbon' if the value has not changed}} + GlobalCBONPtrToIncompleteTy = 0x0; + // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + GlobalCBONPtrToIncompleteTy[0] = 0; + // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cbon(GlobalCBONPtrToIncompleteTy, external_count); +} + + + +static int global_count_cbon; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +static struct IncompleteStructTy* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInit; // expected-note 4{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +static Incomplete_Struct_t* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInitTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + + + +void use_GlobalCBONPtrImplicitInit(void) { + // expected-error@+2{{cannot assign to 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBONPtrImplicitInit' requires corresponding assignment to 'global_count_cbon'; add self assignment 'global_count_cbon = global_count_cbon' if the value has not changed}} + GlobalCBONPtrImplicitInit = 0x0; + // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + GlobalCBONPtrImplicitInit[0] = 0; + // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + consume_incomplete_cbon(GlobalCBONPtrImplicitInit, global_count_cbon); +} + + + +int global_count_cbon_non_static = 0; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInit = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInitTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +void use_GlobalCBONPtrExplicitInit(void) { + // No diagnostics because the VarDecl is marked as invalid at this point + GlobalCBONPtrExplicitInit = 0x0; + GlobalCBONPtrExplicitInit[0] = 0; + consume_incomplete_cbon(GlobalCBONPtrExplicitInit, global_count_cbon_non_static); +} + + + +// This is very unidiomatic C but it seems to be legal. +// expected-warning@+1{{'extern' variable has an initializer}} +extern int global_count_cbon_extern = 0; +// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 +extern struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitExtern = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +// expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 +extern Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitTypeDefExtern = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + + +// TODO: We should consider allowing this given that the pointee type size isn't +// really needed when the count is 0 (rdar://129424147) +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCount; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCountTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCount = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +// Unlike `__counted_by` assigning 0x0 (implicitly or explicitly) is allowed for `__counted_by_or_null` +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCount; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCount = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +//------------------------------------------------------------------------------ +// No explicit forward decl +//------------------------------------------------------------------------------ + +// expected-note@+1 2{{consider providing a complete definition for 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl')}} +typedef struct NoExplicitForwardDecl NoExplicitForwardDecl_t; + +extern NoExplicitForwardDecl_t* __counted_by(0) NoExplicitForwardDeclGlobalCBPtr; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_NoExplicitForwardDeclGlobalCBPtr(void) { + // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBPtr' with '__counted_by' attributed type 'NoExplicitForwardDecl_t *__single __counted_by(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete}} + NoExplicitForwardDeclGlobalCBPtr = 0x0; +} + +extern NoExplicitForwardDecl_t* __counted_by_or_null(0) NoExplicitForwardDeclGlobalCBONPtr; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +void consume_NoExplicitForwardDeclGlobalCBONPtr(void) { + // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBONPtr' with '__counted_by_or_null' attributed type 'NoExplicitForwardDecl_t *__single __counted_by_or_null(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete}} + NoExplicitForwardDeclGlobalCBONPtr = 0x0; +} + +//------------------------------------------------------------------------------ +// Array element initialization +// +// Currently this appears to be forbidden +//------------------------------------------------------------------------------ + +void array_elts_init_cb(void) { + int size; + // expected-error@+1{{'__counted_by' attribute on nested pointer type is only allowed on indirect parameters}} + struct IncompleteStructTy*__counted_by(size) arr[2] = { 0x0, 0x0 }; +} + +void array_elts_init_cbon(void) { + int size; + // expected-error@+1{{'__counted_by_or_null' attribute on nested pointer type is only allowed on indirect parameters}} + struct IncompleteStructTy*__counted_by_or_null(size) arr[2] = { 0x0, 0x0 }; +} + +//------------------------------------------------------------------------------ +// Casting +//------------------------------------------------------------------------------ +// TODO: These should cause errors to be emitted. +// rdar://131621712 +void explicit_cast_cb_to_single(struct IncompleteStructTy* p) { + struct IncompleteStructTy* __single tmp = + (struct IncompleteStructTy* __counted_by(1)) p; +} + +void explicit_cast_cbon_to_single(struct IncompleteStructTy* p) { + struct IncompleteStructTy* __single tmp = + (struct IncompleteStructTy* __counted_by_or_null(1)) p; +} + + +void explicit_cast_cb_to_bidi(struct IncompleteStructTy* p) { + // TODO: This diagnostic is misleading. It says __single but it should probably be `__counted_by(2)`. rdar://133002045 + // expected-error@+1{{cannot initialize indexable pointer with type 'struct IncompleteStructTy *__bidi_indexable' from __single pointer to incomplete type 'struct IncompleteStructTy *__single'; consider declaring pointer 'local_bidi' as '__single'}} + struct IncompleteStructTy* local_bidi = (struct IncompleteStructTy* __counted_by(2)) p; // expected-note{{pointer 'local_bidi' declared here}} +} + +void explicit_cast_cbon_to_bidi(struct IncompleteStructTy* p) { + // TODO: This diagnostic is misleading. It says __single but it should probably be `__counted_by(2)`. rdar://133002045 + // expected-error@+1{{cannot initialize indexable pointer with type 'struct IncompleteStructTy *__bidi_indexable' from __single pointer to incomplete type 'struct IncompleteStructTy *__single'; consider declaring pointer 'local_bidi' as '__single'}} + struct IncompleteStructTy* local_bidi = (struct IncompleteStructTy* __counted_by_or_null(2)) p; // expected-note{{pointer 'local_bidi' declared here}} +} + +//------------------------------------------------------------------------------ +// Completing the pointee type allows usage +//------------------------------------------------------------------------------ + +// expected-note@+1 20{{consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy'}} +struct IncompleteLaterCompletedStructTy; + +// Confirm using the type is an error at this point +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrExpectErr = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrTentativeDefUseWillErr; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrExpectErr = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrTentativeDefUseWillErr; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +struct StructPtrIncompleteLaterCompleted { + int count; + struct IncompleteLaterCompletedStructTy*__counted_by(count) ptr; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} +}; +struct StructCBONPtrIncompleteLaterCompleted { + int count; + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(count) ptr; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void consume_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by(0) p); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_CBON_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) p); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +struct IncompleteLaterCompletedStructTy*__counted_by(0) ret_IncompleteLaterCompletedStructTy(void); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) ret_CBON_IncompleteLaterCompletedStructTy(void); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) test_cb_expect_err( // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by(0) param) { // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by(0) local; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + + // expected-error@+1{{cannot assign to 'GlobalCBPtrTentativeDefUseWillErr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + GlobalCBPtrTentativeDefUseWillErr = 0; + + // expected-error@+1{{cannot initialize 'StructPtrIncompleteLaterCompleted::ptr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct StructPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; + + struct StructPtrIncompleteLaterCompleted tmp2; + // expected-error@+1{{cannot use 'tmp2.ptr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + consume_IncompleteLaterCompletedStructTy(tmp2.ptr); + + // expected-error@+1{{cannot pass argument to parameter 'p' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + consume_IncompleteLaterCompletedStructTy(0x0); + + // expected-error@+1{{cannot call 'ret_IncompleteLaterCompletedStructTy' with '__counted_by' attributed return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + ret_IncompleteLaterCompletedStructTy(); + + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + return 0x0; +} + +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) test_cbon_expect_err( // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) param) { // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) local; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + + // expected-error@+1{{cannot assign to 'GlobalCBONPtrTentativeDefUseWillErr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + GlobalCBONPtrTentativeDefUseWillErr = 0; + + // expected-error@+1{{cannot initialize 'StructCBONPtrIncompleteLaterCompleted::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct StructCBONPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; + + struct StructCBONPtrIncompleteLaterCompleted tmp2; + // expected-error@+1{{cannot use 'tmp2.ptr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + consume_CBON_IncompleteLaterCompletedStructTy(tmp2.ptr); + + // expected-error@+1{{cannot pass argument to parameter 'p' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + consume_CBON_IncompleteLaterCompletedStructTy(0x0); + + // expected-error@+1{{cannot call 'ret_CBON_IncompleteLaterCompletedStructTy' with '__counted_by_or_null' attributed return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + ret_CBON_IncompleteLaterCompletedStructTy(); + + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + return 0x0; +} + + +// Now complete the type and confirm it can be used +struct IncompleteLaterCompletedStructTy { + int field; +}; + +struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrExpectNoErr = 0x0; + +struct IncompleteLaterCompletedStructTy*__counted_by(0) test_cb_expect_no_err( + struct IncompleteLaterCompletedStructTy*__counted_by(0) param) { + struct IncompleteLaterCompletedStructTy*__counted_by(0) local; + + GlobalCBPtrTentativeDefUseWillErr = 0; + + struct StructPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; + struct StructPtrIncompleteLaterCompleted tmp2; + consume_IncompleteLaterCompletedStructTy(tmp2.ptr); + + consume_IncompleteLaterCompletedStructTy(0x0); + ret_IncompleteLaterCompletedStructTy(); + + return 0x0; +} + +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) test_cbon_expect_no_err( + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) param) { + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) local; + + GlobalCBONPtrTentativeDefUseWillErr = 0; + + struct StructCBONPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; + struct StructCBONPtrIncompleteLaterCompleted tmp2; + consume_CBON_IncompleteLaterCompletedStructTy(tmp2.ptr); + + consume_CBON_IncompleteLaterCompletedStructTy(0x0); + ret_CBON_IncompleteLaterCompletedStructTy(); + + return 0x0; +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-null.c b/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-null.c new file mode 100644 index 0000000000000..5435448a640ec --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-null.c @@ -0,0 +1,71 @@ +// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s + +#include +#include + +void const_count_callee(int *__counted_by(10) ccp); + +int *__counted_by(10) const_count(void) { + // expected-error@+1{{initializing 'cc' of type 'int *__single __counted_by(10)' (aka 'int *__single') and count value of 10 with null always fails}} + int *__counted_by(10) cc = NULL; + + // expected-error@+1{{assigning null to 'cc' of type 'int *__single __counted_by(10)' (aka 'int *__single') with count value of 10 always fails}} + cc = NULL; + + // expected-error@+1{{passing null to parameter 'ccp' of type 'int *__single __counted_by(10)' (aka 'int *__single') with count value of 10 always fails}} + const_count_callee(NULL); + + // rs-error@+1{{returning null from a function with result type 'int *__single __counted_by(10)' (aka 'int *__single') and count value of 10 always fails}} + return NULL; +} + +void const_size_callee(char *__sized_by(10) csp); + +char *__sized_by(10) const_size(void) { + // expected-error@+1{{initializing 'cs' of type 'char *__single __sized_by(10)' (aka 'char *__single') and size value of 10 with null always fails}} + char *__sized_by(10) cs = NULL; + + // expected-error@+1{{assigning null to 'cs' of type 'char *__single __sized_by(10)' (aka 'char *__single') with size value of 10 always fails}} + cs = NULL; + + // expected-error@+1{{passing null to parameter 'csp' of type 'char *__single __sized_by(10)' (aka 'char *__single') with size value of 10 always fails}} + const_size_callee(NULL); + + // rs-error@+1{{returning null from a function with result type 'char *__single __sized_by(10)' (aka 'char *__single') and size value of 10 always fails}} + return NULL; +} + +void dynamic_count_callee(int *__counted_by(len) dcp, int len); + +void dynamic_count(void) { + // expected-error@+2{{initializing 'dc' of type 'int *__single __counted_by(len)' (aka 'int *__single') and count value of 10 with null always fails}} + int len = 10; + int *__counted_by(len) dc = NULL; + + // expected-error@+2{{assigning null to 'dc' of type 'int *__single __counted_by(len)' (aka 'int *__single') with count value of 10 always fails}} + len = 10; + dc = NULL; + + // expected-error@+1{{passing null to parameter 'dcp' of type 'int *__single __counted_by(len)' (aka 'int *__single') with count value of 10 always fails}} + dynamic_count_callee(NULL, 10); +} + +void dynamic_size_callee(char *__sized_by(size) dsp, int size); + +void dynamic_size(void) { + // expected-error@+2{{initializing 'ds' of type 'char *__single __sized_by(size)' (aka 'char *__single') and size value of 10 with null always fails}} + int size = 10; + char *__sized_by(size) ds = NULL; + + // expected-error@+2{{assigning null to 'ds' of type 'char *__single __sized_by(size)' (aka 'char *__single') with size value of 10 always fails}} + size = 10; + ds = NULL; + + // expected-error@+1{{passing null to parameter 'dsp' of type 'char *__single __sized_by(size)' (aka 'char *__single') with size value of 10 always fails}} + dynamic_size_callee(NULL, 10); +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-return.c b/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-return.c new file mode 100644 index 0000000000000..e8e421e2dcb8b --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/dynamic-count-ptr-return.c @@ -0,0 +1,148 @@ + +// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=guarded %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=guarded %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected -fbounds-safety-bringup-missing-checks=return_size %s + +// guarded-no-diagnostics + +#include +#include + +// expected-note@+1 2{{'g_array' declared here}} +static int32_t g_array[42]; + +// __counted_by()/__sized_by() with a negative count and any pointer. + +int *__counted_by(-1) negative_cb(void) { + // expected-error@+1{{negative count value of -1 for 'int *__single __counted_by(-1)'}} + return 0; +} + +void *__sized_by(-1) negative_sb(void) { + // expected-error@+1{{negative size value of -1 for 'void *__single __sized_by(-1)'}} + return 0; +} + +// __counted_by_or_null()/__sized_by_or_null() with a negative count and nonnull ptr. + +int32_t *__counted_by_or_null(-1) negative_cbn(void) { + // expected-error@+1{{negative count value of -1 for 'int32_t *__single __counted_by_or_null(-1)'}} + return g_array; +} + +void *__sized_by_or_null(-1) negative_sbn(void) { + // expected-error@+1{{negative size value of -1 for 'void *__single __sized_by_or_null(-1)'}} + return g_array; +} + +// __counted_by()/__sized_by() with a positive count and an array. + +int32_t *__counted_by(42) array_cb_ok(void) { + return g_array; +} + +void *__sized_by(42*4) array_sb_ok(void) { + return g_array; +} + +int32_t *__counted_by(43) array_cb_bad(void) { + // expected-error-re@+1{{returning array 'g_array' (which has 42 elements) from a function with result type 'int32_t *__single __counted_by(43)'{{.*}} and count value of 43 always fails}} + return g_array; +} + +void *__sized_by(42*4+1) array_sb_bad(void) { + // expected-error-re@+1{{returning array 'g_array' (which has 168 bytes) from a function with result type 'void *__single __sized_by(169)'{{.*}} and size value of 169 always fails}} + return g_array; +} + +// __single to __counted_by()/__sized_by() with a positive count/size. + +int32_t *__counted_by(1) single_cb_ok(int32_t *__single p) { + return p; +} + +void *__sized_by(4) single_sb_ok(int32_t *__single p) { + return p; +} + +int32_t *__counted_by(2) single_cb_bad(int32_t *__single p) { + // expected-error-re@+1{{returning 'int32_t *__single'{{.*}} from a function with result type 'int32_t *__single __counted_by(2)'{{.*}} and count value of 2 always fails}} + return p; +} + +void *__sized_by(5) single_sb_bad(int32_t *__single p) { + // expected-error-re@+1{{returning 'int32_t *__single'{{.*}} with pointee of size 4 from a function with result type 'void *__single __sized_by(5)'{{.*}} and size value of 5 always fails}} + return p; +} + +// NULL to __counted_by()/__sized_by() with a positive count. + +int *__counted_by(42) null_cb(int arg) { + switch (arg) { + case 0: + // expected-error@+1{{returning null from a function with result type 'int *__single __counted_by(42)' (aka 'int *__single') and count value of 42 always fails}} + return (void*) 0; + case 1: + // expected-error@+1{{returning null from a function with result type 'int *__single __counted_by(42)' (aka 'int *__single') and count value of 42 always fails}} + return (int*) 0; + } + + // expected-error@+1{{returning null from a function with result type 'int *__single __counted_by(42)' (aka 'int *__single') and count value of 42 always fails}} + return 0; +} + +int *__counted_by(size) null_cb_sized(int arg, int size) { + // No diagnostics + switch (arg) { + case 0: + return 0; + case 1: + return (void*) 0; + case 2: + return (int*) 0; + } + return 0; +} + +char *__sized_by(42) null_sb(int arg) { + switch (arg) { + case 0: + // expected-error@+1{{returning null from a function with result type 'char *__single __sized_by(42)' (aka 'char *__single') and size value of 42 always fails}} + return (void*) 0; + case 1: + // expected-error@+1{{returning null from a function with result type 'char *__single __sized_by(42)' (aka 'char *__single') and size value of 42 always fails}} + return (char*) 0; + } + + // expected-error@+1{{returning null from a function with result type 'char *__single __sized_by(42)' (aka 'char *__single') and size value of 42 always fails}} + return 0; +} + +int *__sized_by(size) null_sb_sized(int arg, int size) { + // No diagnostics + switch (arg) { + case 0: + return 0; + case 1: + return (void*) 0; + case 2: + return (int*) 0; + } + return 0; +} + + +// The __counted_by_or_null()/__sized_by_or_null() pointer is set to some unknown value with a negative count/size. + +int *__counted_by_or_null(-1) negative_cbn_unknown(int *p) { + // expected-error@+1{{possibly returning non-null from a function with result type 'int *__single __counted_by_or_null(-1)' (aka 'int *__single') with count value of -1; explicitly return null to remove this warning}} + return p; +} + +void *__sized_by_or_null(-1) negative_sbn_unknown(int *p) { + // expected-error@+1{{possibly returning non-null from a function with result type 'void *__single __sized_by_or_null(-1)' (aka 'void *__single') with size value of -1; explicitly return null to remove this warning}} + return p; +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/ended_by_assignments.c b/clang/test/BoundsSafety-legacy-checks/Sema/ended_by_assignments.c new file mode 100644 index 0000000000000..77f9bae76146b --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/ended_by_assignments.c @@ -0,0 +1,57 @@ +// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +#include + +int *__ended_by(end) func_ret_end(int *end) { + // rs-error@+1{{parameter 'end' is implicitly read-only due to being used by the '__ended_by' attribute in the return type of 'func_ret_end' ('int *__single __ended_by(end)' (aka 'int *__single'))}} + end = 0; + return end; +} + +int *__ended_by(end) func_ret_end2(int *__ended_by(end) start, int *end) { + return start + 1; +} + +void func_out_start_out_end(int *__ended_by(*out_end) *out_start, + int **out_end) { + out_start = 0; + out_end = 0; +} + +void func_out_start_in_end(int *__ended_by(end) *out_start, + int *end) { + *out_start = *out_start + 1; + // expected-error@+1{{parameter 'end' referred to by an indirect '__ended_by' pointer is implicitly read-only}} + end--; +} + +void func_out_start_in_end2(int *__ended_by(end) *out_start, + int *end) { + // expected-error@+1{{parameter 'end' referred to by an indirect '__ended_by' pointer is implicitly read-only}} + end--; +} + +void func_out_start_in_end3(int *__ended_by(end) *out_start, + int *end) { + *out_start = *out_start + 1; +} + +void func_in_start_out_end(int *__ended_by(*out_end) start, + int **out_end) { + // expected-error@+1{{parameter 'start' with '__ended_by' attribute depending on an indirect end pointer is implicitly read-only}} + start++; +} + +void func_in_start_out_end2(int *__ended_by(*out_end) start, + int **out_end) { + *out_end = *out_end - 1; + // expected-error@+1{{parameter 'start' with '__ended_by' attribute depending on an indirect end pointer is implicitly read-only}} + start++; +} + +void func_in_start_out_end3(int *__ended_by(*out_end) start, + int **out_end) { + *out_end = *out_end - 1; +} diff --git a/clang/test/BoundsSafety-legacy-checks/Sema/sized-by-ptr-arith-constant-count.c b/clang/test/BoundsSafety-legacy-checks/Sema/sized-by-ptr-arith-constant-count.c new file mode 100644 index 0000000000000..277878d0c6e45 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/Sema/sized-by-ptr-arith-constant-count.c @@ -0,0 +1,767 @@ + + +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=indirect_count_update -verify=expected,legacy,extra %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=compound_literal_init -verify=expected,legacy,cli %s +#include + +void consume_sb(int* __sized_by(3) p); +void consume_sbon(int* __sized_by_or_null(3) p); + +struct sb { + int count; + int* __sized_by(count) buf; +}; + +struct sbon { + int count; + int* __sized_by_or_null(count) buf; +}; + +void side_effect(void); + +int global_arr [2] = {0}; +// expected-note@+2 4{{__sized_by attribute is here}} +// extra-note@+1 2{{__sized_by attribute is here}} +int*__sized_by(2) global_sb = global_arr; +// expected-note@+2 4{{__sized_by_or_null attribute is here}} +// extra-note@+1 2{{__sized_by_or_null attribute is here}} +int*__sized_by_or_null(2) global_sbon = global_arr; + +const int const_size = 2; +// expected-note@+2 4{{__sized_by attribute is here}} +// extra-note@+1 2{{__sized_by attribute is here}} +int*__sized_by(const_size) global_sb_const_qual_count = global_arr; +// expected-note@+2 4{{__sized_by_or_null attribute is here}} +// extra-note@+1 2{{__sized_by_or_null attribute is here}} +int*__sized_by_or_null(const_size) global_sbon_const_qual_count = global_arr; + +// expected-note@+2 4{{__sized_by attribute is here}} +// extra-note@+1 2{{__sized_by attribute is here}} +int*__sized_by(1+1) global_sb_opo = global_arr; +// expected-note@+2 4{{__sized_by_or_null attribute is here}} +// extra-note@+1 2{{__sized_by_or_null attribute is here}} +int*__sized_by_or_null(1+1) global_sbon_opo = global_arr; + +// legacy-note@+3 1{{__sized_by attribute is here}} +// expected-note@+2 8{{__sized_by attribute is here}} +// extra-note@+1 3{{__sized_by attribute is here}} +int* __sized_by(2) test_sb(int* __sized_by(3) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__sized_by attribute is here}} + // extra-note@+1 2{{__sized_by attribute is here}} + int* __sized_by(2) local_sb = p; + local_sb = p; // OK + side_effect(); + ++local_sb; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sb; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local_sb--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local_sb += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sb++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sb = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sb = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *local_sb-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local = local_sb + 1; // OK because `local_sb` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_sb++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sb; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sb--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + --global_sb; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sb -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sb++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sb = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sb-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *--global_sb = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb = global_sb + 1; // OK because `global_sb` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + consume_sb(++p); // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + struct sb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + S = (struct sb){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} +} + +// legacy-note@+3 1{{__sized_by attribute is here}} +// expected-note@+2 8{{__sized_by attribute is here}} +// extra-note@+1 3{{__sized_by attribute is here}} +int* __sized_by(2) test_sb_constant_fold_count(int* __sized_by(2+1) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__sized_by attribute is here}} + // extra-note@+1 2{{__sized_by attribute is here}} + int* __sized_by(1+1) local_sb = p; + local_sb = p; // OK + side_effect(); + ++local_sb; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sb; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local_sb--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local_sb += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sb++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sb = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sb = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *local_sb-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local = local_sb + 1; // OK because `local_sb` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_sb_opo++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sb_opo; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sb_opo--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + --global_sb_opo; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb_opo += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sb_opo -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sb_opo++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sb_opo = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sb_opo-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *--global_sb_opo = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb_opo = global_sb_opo + 1; // OK because `global_sb` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + consume_sb(++p); // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + struct sb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + S = (struct sb){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size of 3 always traps}} +} + +// legacy-note@+3 1{{__sized_by attribute is here}} +// expected-note@+2 8{{__sized_by attribute is here}} +// extra-note@+1 3{{__sized_by attribute is here}} +int* __sized_by(size) test_sb_const_qualified_size(const int size, int* __sized_by(size) p) { + int* local; + // Modify local var + const int local_size = 2; + // expected-note@+2 4{{__sized_by attribute is here}} + // extra-note@+1 2{{__sized_by attribute is here}} + int* __sized_by(local_size) local_sb = p; + side_effect(); + local_sb = p; // OK + + side_effect(); + ++local_sb; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sb; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local_sb--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + local_sb += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sb -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sb++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sb = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sb = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *local_sb-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + local = local_sb + 1; // OK because `local_sb` gets promoted to a __bidi_indexable first. + side_effect(); + + // Modify global + global_sb_const_qual_count++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sb_const_qual_count; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + --global_sb_const_qual_count; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb_const_qual_count += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sb_const_qual_count-= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sb_const_qual_count++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sb_const_qual_count = 1; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sb_const_qual_count-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *--global_sb_const_qual_count = 1; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + global_sb_const_qual_count = global_sb_const_qual_count + 1; // OK because `global_sb` gets promoted to a __bidi_indexable first. + + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by' pointer always traps}} + + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + + side_effect(); + + consume_sb(++p); // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + struct sb S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by' pointer with side effects is not yet supported}} + S = (struct sb){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by' attributed pointer with constant size 'size' always traps}} +} + +// legacy-note@+3 1{{__sized_by_or_null attribute is here}} +// expected-note@+2 8{{__sized_by_or_null attribute is here}} +// extra-note@+1 3{{__sized_by_or_null attribute is here}} +int* __sized_by_or_null(2) test_sbon(int* __sized_by_or_null(3) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__sized_by_or_null attribute is here}} + // extra-note@+1 2{{__sized_by_or_null attribute is here}} + int* __sized_by_or_null(2) local_sbon = p; + local_sbon = p; // OK + side_effect(); + ++local_sbon; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sbon; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local_sbon--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local_sbon += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sbon++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sbon = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sbon = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *local_sbon-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local = local_sbon + 1; // OK because `local_sbon` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_sbon++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sbon; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sbon--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + --global_sbon; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sbon -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sbon++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sbon = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sbon-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *--global_sbon = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon = global_sbon + 1; // OK because `global_sbon` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + consume_sbon(++p); // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + struct sbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + S = (struct sbon){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} +} + +// legacy-note@+3 1{{__sized_by_or_null attribute is here}} +// expected-note@+2 8{{__sized_by_or_null attribute is here}} +// extra-note@+1 3{{__sized_by_or_null attribute is here}} +int* __sized_by_or_null(2) test_sbon_constant_fold_count(int* __sized_by_or_null(2+1) p) { + int* local; + + // Modify local var + // expected-note@+2 4{{__sized_by_or_null attribute is here}} + // extra-note@+1 2{{__sized_by_or_null attribute is here}} + int* __sized_by_or_null(1+1) local_sbon = p; + local_sbon = p; // OK + side_effect(); + ++local_sbon; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sbon; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local_sbon--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local_sbon += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sbon++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sbon = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sbon = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *local_sbon-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local = local_sbon + 1; // OK because `local_sbon` gets promoted to a __bidi_indexable first. + side_effect(); + + + // Modify global + global_sbon_opo++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sbon_opo; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sbon_opo--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + --global_sbon_opo; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon_opo += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sbon_opo -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sbon_opo++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sbon_opo = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sbon_opo-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *--global_sbon_opo = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon_opo = global_sbon_opo + 1; // OK because `global_sbon` gets promoted to a __bidi_indexable first. + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + consume_sbon(++p); // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + struct sbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + S = (struct sbon){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 3 always traps}} +} + +// legacy-note@+3 1{{__sized_by_or_null attribute is here}} +// expected-note@+2 8{{__sized_by_or_null attribute is here}} +// extra-note@+1 3{{__sized_by_or_null attribute is here}} +int* __sized_by_or_null(size) test_sbon_const_qualified_size(const int size, int* __sized_by_or_null(size) p) { + int* local; + // Modify local var + const int local_size = 2; + // expected-note@+2 4{{__sized_by_or_null attribute is here}} + // extra-note@+1 2{{__sized_by_or_null attribute is here}} + int* __sized_by_or_null(local_size) local_sbon = p; + side_effect(); + local_sbon = p; // OK + + side_effect(); + ++local_sbon; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + --local_sbon; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local_sbon--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + local_sbon += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + local_sbon -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *local_sbon++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++local_sbon = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *--local_sbon = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *local_sbon-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + local = local_sbon + 1; // OK because `local_sbon` gets promoted to a __bidi_indexable first. + side_effect(); + + // Modify global + global_sbon_const_qual_count++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + ++global_sbon_const_qual_count; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + --global_sbon_const_qual_count; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon_const_qual_count += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + global_sbon_const_qual_count-= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *global_sbon_const_qual_count++ = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + *++global_sbon_const_qual_count = 1; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size of 2 always traps}} + side_effect(); + + *global_sbon_const_qual_count-- = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *--global_sbon_const_qual_count = 1; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + global_sbon_const_qual_count = global_sbon_const_qual_count + 1; // OK because `global_sbon` gets promoted to a __bidi_indexable first. + + + // Modify param + ++p; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + p++; // expected-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + --p; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p--; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + p += 1; // expected-error{{compound addition-assignment on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + p -= 1; // expected-error{{compound subtraction-assignment on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + + // Only when -fbounds-safety-bringup-missing-checks=indirect_count_update + *++p = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + *p++ = 0; // extra-error{{positive pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + + *--p = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + side_effect(); + *p-- = 0; // expected-error{{negative pointer arithmetic on '__sized_by_or_null' pointer always traps}} + + + p *= 1; // expected-error{{invalid operands to binary expression}} + p *= 2; // expected-error{{invalid operands to binary expression}} + p |= 2; // expected-error{{invalid operands to binary expression}} + p &= 2; // expected-error{{invalid operands to binary expression}} + p ^= 2; // expected-error{{invalid operands to binary expression}} + p %= 2; // expected-error{{invalid operands to binary expression}} + p <<= 0; // expected-error{{invalid operands to binary expression}} + p >>= 0; // expected-error{{invalid operands to binary expression}} + + // Increment in other contexts + // legacy-error@+2{{multiple consecutive assignments to a dynamic count pointer 'p' must be simplified; keep only one of the assignments}} + // legacy-note@+1{{previously assigned here}} + p++, p = local; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + side_effect(); + *(++p) = 0; // extra-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + + side_effect(); + + consume_sbon(++p); // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + struct sbon S = { + .count = 2, + // legacy-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + .buf = ++p // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + }; + // cli-error@+1{{initalizer for '__sized_by_or_null' pointer with side effects is not yet supported}} + S = (struct sbon){.buf = p++}; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} + + side_effect(); + + return ++p; // expected-error{{pointer arithmetic on '__sized_by_or_null' attributed pointer with constant size 'size' always traps}} +} + +// Warning diagnostic tests + +void downgrade_to_warning(int* __sized_by(4) ptr) { // expected-note{{__sized_by attribute is here}} +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wbounds-safety-externally-counted-ptr-arith-constant-count" + ++ptr; // expected-warning{{positive pointer arithmetic on '__sized_by' attributed pointer with constant size of 4 always traps}} +#pragma clang diagnostic pop +} + +void downgrade_to_ignored(int* __sized_by(4) ptr) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wbounds-safety-externally-counted-ptr-arith-constant-count" + ++ptr; // ok +} diff --git a/clang/test/BoundsSafety-legacy-checks/lit.local.cfg.py b/clang/test/BoundsSafety-legacy-checks/lit.local.cfg.py new file mode 100644 index 0000000000000..69b13058285e3 --- /dev/null +++ b/clang/test/BoundsSafety-legacy-checks/lit.local.cfg.py @@ -0,0 +1,27 @@ +import os + +cc1_substituted = [ False ] +extra_flags = '-fno-bounds-safety-bringup-missing-checks=all' + +def patch_cc1(sub_tuple): + assert isinstance(sub_tuple, tuple) + assert len(sub_tuple) == 2 + subst_name = sub_tuple[0] + + # Match `%clang_cc1`. The `ToolSubst` class inside `lit` adds a bunch of + # regexes around this substitution so we try to match them here to avoid + # matching a substitution that has `%clang_cc1` as a substring. This is + # fragile + if r'%\bclang_cc1\b' not in subst_name: + return sub_tuple + patched_sub = sub_tuple[1] + f' {extra_flags}' + cc1_substituted[0] = True + return (sub_tuple[0], patched_sub) + +config.substitutions = list(map(patch_cc1, config.substitutions)) + +dir_with_patched_sub = os.path.dirname(__file__) +if not cc1_substituted[0]: + lit_config.fatal(f'Failed to add `{extra_flags}` to %clang_cc1 invocations under {dir_with_patched_sub}') +else: + lit_config.note(f'Implicitly passing `{extra_flags}` to %clang_cc1 invocations under {dir_with_patched_sub}') diff --git a/clang/test/BoundsSafety/AST/SystemHeaders/builtin-function-main.c b/clang/test/BoundsSafety/AST/SystemHeaders/builtin-function-main.c index c2b1dafbfeb0a..ffff0967f88f3 100644 --- a/clang/test/BoundsSafety/AST/SystemHeaders/builtin-function-main.c +++ b/clang/test/BoundsSafety/AST/SystemHeaders/builtin-function-main.c @@ -13,300 +13,332 @@ char * __counted_by(len) func(char * __counted_by(len) src_str, int len) { return dst_str; } -// CHECK: TranslationUnitDecl -// CHECK: |-FunctionDecl [[func_static:0x[^ ]+]] {{.+}} static -// CHECK: | |-ParmVarDecl [[var_dst:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_src:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | `-MaterializeSequenceExpr {{.+}} -// CHECK: | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'unsigned long' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | `-AssumptionExpr -// CHECK: | | | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' -// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '>=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | `-IntegerLiteral {{.+}} 0 -// CHECK: | | |-OpaqueValueExpr [[ove_1]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_dst]] -// CHECK: | | |-OpaqueValueExpr [[ove_2]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src]] -// CHECK: | | |-OpaqueValueExpr [[ove_3]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_size]] -// CHECK: | | `-OpaqueValueExpr [[ove]] -// CHECK: | | `-CallExpr -// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' -// CHECK: | | | `-DeclRefExpr {{.+}} -// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' -// CHECK: | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' -// CHECK: | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' -// CHECK: | |-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' -// CHECK: | |-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' -// CHECK: | |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' -// CHECK: | `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: |-FunctionDecl [[func_static_1:0x[^ ]+]] {{.+}} static -// CHECK: | |-ParmVarDecl [[var_dst_1:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_src_1:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size_1:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | `-ReturnStmt -// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | `-MaterializeSequenceExpr {{.+}} -// CHECK: | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'unsigned long' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | `-AssumptionExpr -// CHECK: | | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' -// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '>=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | `-IntegerLiteral {{.+}} 0 -// CHECK: | | |-OpaqueValueExpr [[ove_5]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_dst_1]] -// CHECK: | | |-OpaqueValueExpr [[ove_6]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_1]] -// CHECK: | | |-OpaqueValueExpr [[ove_7]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_size_1]] -// CHECK: | | `-OpaqueValueExpr [[ove_4]] -// CHECK: | | `-CallExpr -// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' -// CHECK: | | | `-DeclRefExpr {{.+}} -// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' -// CHECK: | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' -// CHECK: | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' -// CHECK: | |-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' -// CHECK: | |-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' -// CHECK: | |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' -// CHECK: | `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: |-FunctionDecl [[func_static_2:0x[^ ]+]] {{.+}} static -// CHECK: | |-ParmVarDecl [[var_dst_2:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_src_2:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size_2:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | |-DeclStmt -// CHECK: | | `-VarDecl [[var_tmp:0x[^ ]+]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'void *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'unsigned long' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | | `-AssumptionExpr -// CHECK: | | | | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '>=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | | `-IntegerLiteral {{.+}} 0 -// CHECK: | | | |-OpaqueValueExpr [[ove_9]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_dst_2]] -// CHECK: | | | |-OpaqueValueExpr [[ove_10]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_2]] -// CHECK: | | | |-OpaqueValueExpr [[ove_11]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_size_2]] -// CHECK: | | | `-OpaqueValueExpr [[ove_8]] -// CHECK: | | | `-CallExpr -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' -// CHECK: | | | | `-DeclRefExpr {{.+}} -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' -// CHECK: | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' -// CHECK: | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' -// CHECK: | | |-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' -// CHECK: | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' -// CHECK: | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' -// CHECK: | `-ReturnStmt -// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | `-DeclRefExpr {{.+}} [[var_tmp]] -// CHECK: |-FunctionDecl [[func_static_3:0x[^ ]+]] {{.+}} static -// CHECK: | |-ParmVarDecl [[var_size_3:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | `-ReturnStmt -// CHECK: | `-CallExpr -// CHECK: | |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' -// CHECK: | | `-DeclRefExpr {{.+}} -// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_size_3]] -// CHECK: |-FunctionDecl [[func_static_4:0x[^ ]+]] {{.+}} static -// CHECK: | |-ParmVarDecl [[var_size_4:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | |-DeclStmt -// CHECK: | | `-VarDecl [[var_tmp_1:0x[^ ]+]] -// CHECK: | | `-CallExpr -// CHECK: | | |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' -// CHECK: | | | `-DeclRefExpr {{.+}} -// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_size_4]] -// CHECK: | `-ReturnStmt -// CHECK: | `-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | `-DeclRefExpr {{.+}} [[var_tmp_1]] -// CHECK: `-FunctionDecl [[func_func:0x[^ ]+]] {{.+}} func -// CHECK: |-ParmVarDecl [[var_src_str:0x[^ ]+]] -// CHECK: |-ParmVarDecl [[var_len:0x[^ ]+]] -// CHECK: | `-DependerDeclsAttr -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_len2:0x[^ ]+]] -// CHECK: | |-IntegerLiteral {{.+}} 0 -// CHECK: | `-DependerDeclsAttr -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_dst_str:0x[^ ]+]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsCheckExpr {{.+}} '((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) && __builtin_get_pointer_lower_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) <= ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && len <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) - ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && 0 <= len' -// CHECK: | | |-BinaryOperator {{.+}} 'char *__single __counted_by(len2)':'char *__single' '=' -// CHECK: | | | |-DeclRefExpr {{.+}} [[var_dst_str]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-GetBoundExpr {{.+}} lower -// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: | | | |-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-IntegerLiteral {{.+}} 0 -// CHECK: | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' -// CHECK: | |-OpaqueValueExpr [[ove_12]] -// CHECK: | | `-ParenExpr -// CHECK: | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | `-ForgePtrExpr -// CHECK: | | |-ParenExpr -// CHECK: | | | `-CallExpr -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'void *(*__single)(int)' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[func_static_3]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: | | |-ImplicitCastExpr {{.+}} 'unsigned long' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-ParenExpr -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: | `-OpaqueValueExpr [[ove_13]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BinaryOperator {{.+}} 'int' '=' -// CHECK: | | |-DeclRefExpr {{.+}} [[var_len2]] -// CHECK: | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' -// CHECK: | |-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' -// CHECK: | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' -// CHECK: |-CallExpr -// CHECK: | |-ImplicitCastExpr {{.+}} 'void (*__single)(void *restrict, void *restrict, int)' -// CHECK: | | `-DeclRefExpr {{.+}} [[func_static]] -// CHECK: | |-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | |-OpaqueValueExpr [[ove_14]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_dst_str]] -// CHECK: | | | `-OpaqueValueExpr [[ove_15]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len2]] -// CHECK: | | |-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' -// CHECK: | |-ImplicitCastExpr {{.+}} 'void *' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | |-OpaqueValueExpr [[ove_16]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_str]] -// CHECK: | | | `-OpaqueValueExpr [[ove_17]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: | | |-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: `-ReturnStmt -// CHECK: `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' -// CHECK: | |-OpaqueValueExpr [[ove_18]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_dst_str]] -// CHECK: | `-OpaqueValueExpr [[ove_19]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_len2]] -// CHECK: |-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' -// CHECK: `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}TranslationUnitDecl +// CHECK: {{^}}|-FunctionDecl [[func_static:0x[^ ]+]] {{.+}} static +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_dst:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | `-AssumptionExpr +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_dst]] +// CHECK-NEXT: {{^}}| | |-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_src]] +// CHECK-NEXT: {{^}}| | |-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_size]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | `-CallExpr +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' +// CHECK: {{^}}| | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_1]] {{.*}} 'void *' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_2]] {{.*}} 'void *' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_3]] {{.*}} 'unsigned long' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}|-FunctionDecl [[func_static_1:0x[^ ]+]] {{.+}} static +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_dst_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | `-AssumptionExpr +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_5]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_dst_1]] +// CHECK-NEXT: {{^}}| | |-OpaqueValueExpr [[ove_6]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_src_1]] +// CHECK-NEXT: {{^}}| | |-OpaqueValueExpr [[ove_7]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_size_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_4]] +// CHECK-NEXT: {{^}}| | `-CallExpr +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' +// CHECK: {{^}}| | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_5]] {{.*}} 'void *' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_6]] {{.*}} 'void *' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_7]] {{.*}} 'unsigned long' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_4]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}|-FunctionDecl [[func_static_2:0x[^ ]+]] {{.+}} static +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_dst_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_tmp:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'void *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'void *' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| | | | | `-AssumptionExpr +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | | `-BinaryOperator {{.+}} 'int' '>=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_9]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_dst_2]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_10]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_src_2]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_11]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_size_2]] +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_8]] +// CHECK-NEXT: {{^}}| | | `-CallExpr +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)(*)(void *__single __sized_by(function-parameter-0-2), const void *__single __sized_by(function-parameter-0-2), unsigned long)' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' +// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'const void *__single __sized_by(function-parameter-0-2)':'const void *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_9]] {{.*}} 'void *' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] {{.*}} 'void *' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_11]] {{.*}} 'unsigned long' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_8]] {{.*}} 'void *__single __sized_by(function-parameter-0-2)':'void *__single' +// CHECK: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_tmp]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_static_3:0x[^ ]+]] {{.+}} static +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-CallExpr +// CHECK-NEXT: {{^}}| |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_size_3]] +// CHECK: {{^}}|-FunctionDecl [[func_static_4:0x[^ ]+]] {{.+}} static +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_tmp_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-CallExpr +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'void *(*)(unsigned long)' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_size_4]] +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_tmp_1]] +// CHECK-NEXT: {{^}}`-FunctionDecl [[func_func:0x[^ ]+]] {{.+}} func +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_src_str:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK-NEXT: {{^}} | `-DependerDeclsAttr +// CHECK-NEXT: {{^}} `-CompoundStmt +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_len2:0x[^ ]+]] +// CHECK-NEXT: {{^}} | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | `-DependerDeclsAttr +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_dst_str:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-BoundsCheckExpr {{.+}} '((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) && __builtin_get_pointer_lower_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) <= ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && len <= __builtin_get_pointer_upper_bound(((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len)))) - ((char *__bidi_indexable)__builtin_unsafe_forge_bidi_indexable((malloc(len)), (len))) && 0 <= len' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'char *__single __counted_by(len2)':'char *__single' '=' +// CHECK-NEXT: {{^}} | | | |-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_12]] +// CHECK-NEXT: {{^}} | | `-ParenExpr +// CHECK-NEXT: {{^}} | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | `-ForgePtrExpr +// CHECK-NEXT: {{^}} | | |-ParenExpr +// CHECK-NEXT: {{^}} | | | `-CallExpr +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void *(*__single)(int)' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_static_3]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK-NEXT: {{^}} | | |-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | | `-ParenExpr +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_13]] +// CHECK-NEXT: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '=' +// CHECK-NEXT: {{^}} | | |-DeclRefExpr {{.+}} [[var_len2]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int' +// CHECK: {{^}} |-CallExpr +// CHECK-NEXT: {{^}} | |-ImplicitCastExpr {{.+}} 'void (*__single)(void *restrict, void *restrict, int)' +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[func_static]] +// CHECK-NEXT: {{^}} | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' +// CHECK-NEXT: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | |-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_14]] +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_15]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_len2]] +// CHECK-NEXT: {{^}} | | |-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}} | |-ImplicitCastExpr {{.+}} 'void *' +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'void *__bidi_indexable' +// CHECK-NEXT: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | |-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}} | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_16]] +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_src_str]] +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_17]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK-NEXT: {{^}} | | |-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK-NEXT: {{^}} `-ReturnStmt +// CHECK-NEXT: {{^}} `-BoundsCheckExpr {{.+}} 'dst_str <= __builtin_get_pointer_upper_bound(dst_str) && __builtin_get_pointer_lower_bound(dst_str) <= dst_str && len <= __builtin_get_pointer_upper_bound(dst_str) - dst_str && 0 <= len' +// CHECK-NEXT: {{^}} |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_21]] {{.*}} 'int' +// CHECK: {{^}} |-OpaqueValueExpr [[ove_18]] +// CHECK-NEXT: {{^}} | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | |-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_20]] {{.*}} 'int' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_19]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_dst_str]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_20]] +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_len2]] +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__single __counted_by(len2)':'char *__single' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_20]] {{.*}} 'int' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_21]] +// CHECK-NEXT: {{^}} `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} `-DeclRefExpr {{.+}} [[var_len]] diff --git a/clang/test/BoundsSafety/AST/count-attrs.c b/clang/test/BoundsSafety/AST/count-attrs.c index 321453c08a7ec..f39c97cb69c5d 100644 --- a/clang/test/BoundsSafety/AST/count-attrs.c +++ b/clang/test/BoundsSafety/AST/count-attrs.c @@ -1,5 +1,3 @@ - - // RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety %s | FileCheck %s // RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s | FileCheck %s #include @@ -37,82 +35,99 @@ void test(void) { int *__counted_by(len) frob_body(int len) { return 0; } int *__sized_by(len) byte_frob_body(int len) { return 0; } -// CHECK:TranslationUnitDecl {{.*}} -// CHECK:|-FunctionDecl {{.*}} frob 'int *__single __counted_by(len)(int)' -// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' -// CHECK-NEXT:|-FunctionDecl {{.*}} byte_frob 'int *__single __sized_by(len)(int)' -// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' -// CHECK-NEXT:|-FunctionDecl {{.*}} alloc_bytes 'void *__single(int)' -// CHECK-NEXT:| |-ParmVarDecl {{.*}} byte_count 'int' -// CHECK-NEXT:| `-AllocSizeAttr {{.*}} 1 -// CHECK-NEXT:|-TypedefDecl {{.*}} referenced int_array_t '__array_decay_discards_count_in_parameters int[10]':'int[10]' -// CHECK-NEXT:| `-MacroQualifiedType {{.*}} '__array_decay_discards_count_in_parameters int[10]' sugar -// CHECK-NEXT:| `-AttributedType {{.*}} 'int[10] __attribute__((decay_discards_count_in_parameters))' sugar -// CHECK-NEXT:| `-ParenType {{.*}} 'int[10]' sugar -// CHECK-NEXT:| `-ConstantArrayType {{.*}} 'int[10]' 10 -// CHECK-NEXT:| `-BuiltinType {{.*}} 'int' -// CHECK-NEXT:|-FunctionDecl {{.*}} count_attr_in_bracket 'void (int *__single __counted_by(len), int)' -// CHECK-NEXT:| |-ParmVarDecl {{.*}} buf 'int *__single __counted_by(len)':'int *__single' -// CHECK-NEXT:| `-ParmVarDecl {{.*}} used len 'int' -// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:|-FunctionDecl {{.*}} count_ignored_from_array 'void (int *__single)' -// CHECK-NEXT:| `-ParmVarDecl {{.*}} buf 'int *__single' -// CHECK-NEXT:|-FunctionDecl {{.*}} count_ignored_and_attr 'void (int *__single __counted_by(count), int)' -// CHECK-NEXT:| |-ParmVarDecl {{.*}} buf 'int *__single __counted_by(count)':'int *__single' -// CHECK-NEXT:| `-ParmVarDecl {{.*}} used count 'int' -// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:|-RecordDecl {{.*}} struct s definition -// CHECK-NEXT:| |-FieldDecl {{.*}} bp 'int *__single __counted_by(l)':'int *__single' -// CHECK-NEXT:| |-FieldDecl {{.*}} bp2 'int *__single __counted_by(l + 1)':'int *__single' -// CHECK-NEXT:| |-FieldDecl {{.*}} bp3 'unsigned char *__single __sized_by(l)':'unsigned char *__single' -// CHECK-NEXT:| |-FieldDecl {{.*}} bp4 'unsigned char *__single __sized_by(l + 1)':'unsigned char *__single' -// CHECK-NEXT:| `-FieldDecl {{.*}} referenced l 'int' -// CHECK-NEXT:| `-DependerDeclsAttr {{.*}} Implicit {{.*}} {{.*}} {{.*}} {{.*}} 0 0 0 0 -// CHECK-NEXT:|-FunctionDecl {{.*}} test 'void (void)' -// CHECK-NEXT:| `-CompoundStmt {{.*}} -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} used n 'int' cinit -// CHECK-NEXT:| | |-IntegerLiteral {{.*}} 'int' 0 -// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} buf1 'int *__single __counted_by(n)':'int *__single' -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} used n2 'int' cinit -// CHECK-NEXT:| | |-IntegerLiteral {{.*}} 'int' 0 -// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} buf2 'int *__single __counted_by(n2)':'int *__single' -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} used n3 'int' cinit -// CHECK-NEXT:| | |-ImplicitCastExpr {{.*}} 'int' -// CHECK-NEXT:| | | `-BinaryOperator {{.*}} 'unsigned long' '*' -// CHECK-NEXT:| | | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'int' -// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'unsigned long' -// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'int' -// CHECK-NEXT:| | | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'n' 'int' -// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} byte_buf1 'unsigned char *__single __sized_by(n3)':'unsigned char *__single' -// CHECK-NEXT:| |-DeclStmt {{.*}} -// CHECK-NEXT:| | `-VarDecl {{.*}} used n4 'int' cinit -// CHECK-NEXT:| | |-ImplicitCastExpr {{.*}} 'int' -// CHECK-NEXT:| | | `-BinaryOperator {{.*}} 'unsigned long' '*' -// CHECK-NEXT:| | | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'int' -// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'unsigned long' -// CHECK-NEXT:| | | `-ImplicitCastExpr {{.*}} 'int' -// CHECK-NEXT:| | | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'n2' 'int' -// CHECK-NEXT:| | `-DependerDeclsAttr {{.*}} Implicit {{.*}} 0 -// CHECK-NEXT:| `-DeclStmt {{.*}} -// CHECK-NEXT:| `-VarDecl {{.*}} byte_buf2 'unsigned char *__single __sized_by(n4)':'unsigned char *__single' -// CHECK-NEXT:|-FunctionDecl {{.*}} frob_body 'int *__single __counted_by(len)(int)' -// CHECK-NEXT:| |-ParmVarDecl {{.*}} used len 'int' -// CHECK-NEXT:| `-CompoundStmt {{.*}} -// CHECK-NEXT:| `-ReturnStmt {{.*}} -// CHECK-NEXT:| `-ImplicitCastExpr {{.*}} 'int *__single __counted_by(len)':'int *__single' -// CHECK-NEXT:| `-IntegerLiteral {{.*}} 'int' 0 -// CHECK-NEXT:`-FunctionDecl {{.*}} byte_frob_body 'int *__single __sized_by(len)(int)' -// CHECK-NEXT: |-ParmVarDecl {{.*}} used len 'int' -// CHECK-NEXT: `-CompoundStmt {{.*}} -// CHECK-NEXT: `-ReturnStmt {{.*}} -// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int *__single __sized_by(len)':'int *__single' -// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 +// CHECK: {{^}}TranslationUnitDecl +// CHECK: {{^}}|-FunctionDecl [[func_frob:0x[^ ]+]] {{.+}} frob +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_byte_frob:0x[^ ]+]] {{.+}} byte_frob +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_alloc_bytes:0x[^ ]+]] {{.+}} alloc_bytes +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_byte_count:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-AllocSizeAttr +// CHECK-NEXT: {{^}}|-TypedefDecl +// CHECK-NEXT: {{^}}| `-MacroQualifiedType +// CHECK-NEXT: {{^}}| `-AttributedType +// CHECK-NEXT: {{^}}| `-ParenType +// CHECK-NEXT: {{^}}| `-ConstantArrayType +// CHECK: {{^}}|-FunctionDecl [[func_count_attr_in_bracket:0x[^ ]+]] {{.+}} count_attr_in_bracket +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_buf:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DependerDeclsAttr +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_count_ignored_from_array:0x[^ ]+]] {{.+}} count_ignored_from_array +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_buf_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_count_ignored_and_attr:0x[^ ]+]] {{.+}} count_ignored_and_attr +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_buf_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_count:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DependerDeclsAttr +// CHECK-NEXT: {{^}}|-RecordDecl +// CHECK-NEXT: {{^}}| |-FieldDecl +// CHECK-NEXT: {{^}}| |-FieldDecl +// CHECK-NEXT: {{^}}| |-FieldDecl +// CHECK-NEXT: {{^}}| |-FieldDecl +// CHECK-NEXT: {{^}}| `-FieldDecl +// CHECK-NEXT: {{^}}| `-DependerDeclsAttr +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_test:0x[^ ]+]] {{.+}} test +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_n:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_buf1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_n2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_buf2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_n3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'unsigned long' '*' +// CHECK-NEXT: {{^}}| | | |-UnaryExprOrTypeTraitExpr +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_n]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_byte_buf1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_n4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'unsigned long' '*' +// CHECK-NEXT: {{^}}| | | |-UnaryExprOrTypeTraitExpr +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'unsigned long' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_n2]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-DeclStmt +// CHECK-NEXT: {{^}}| `-VarDecl [[var_byte_buf2:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_frob_body:0x[^ ]+]] {{.+}} frob_body +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-BoundsCheckExpr {{.+}} 'len == 0' +// CHECK-NEXT: {{^}}| |-ImplicitCastExpr {{.+}} 'int *__single __counted_by(len)':'int *__single' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| |-BinaryOperator {{.+}} 'int' '==' +// CHECK-NEXT: {{^}}| | |-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| `-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_len_3]] +// CHECK-NEXT: {{^}}`-FunctionDecl [[func_byte_frob_body:0x[^ ]+]] {{.+}} byte_frob_body +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_len_4:0x[^ ]+]] +// CHECK-NEXT: {{^}} `-CompoundStmt +// CHECK-NEXT: {{^}} `-ReturnStmt +// CHECK-NEXT: {{^}} `-BoundsCheckExpr {{.+}} 'len == 0' +// CHECK-NEXT: {{^}} |-ImplicitCastExpr {{.+}} 'int *__single __sized_by(len)':'int *__single' +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} |-BinaryOperator {{.+}} 'int' '==' +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} |-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}} | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} `-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}} `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} `-DeclRefExpr {{.+}} [[var_len_4]] diff --git a/clang/test/BoundsSafety/AST/counted_by_or_null_call.c b/clang/test/BoundsSafety/AST/counted_by_or_null_call.c index 43f06174950a1..238d9632ed16d 100644 --- a/clang/test/BoundsSafety/AST/counted_by_or_null_call.c +++ b/clang/test/BoundsSafety/AST/counted_by_or_null_call.c @@ -11,7 +11,7 @@ // CHECK: {{^}}| `-CompoundStmt void foo(int *__counted_by_or_null(len) p, int len) {} -// CHECK: {{^}}|-FunctionDecl [[func_caller_1:0x[^ ]+]] {{.+}} caller_1 +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_caller_1:0x[^ ]+]] {{.+}} caller_1 // CHECK-NEXT: {{^}}| `-CompoundStmt // CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} // CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} @@ -19,12 +19,9 @@ void foo(int *__counted_by_or_null(len) p, int len) {} // CHECK-NEXT: {{^}}| | | |-CallExpr // CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' // CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 2 -// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' // CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' @@ -64,12 +61,9 @@ void caller_1() { // CHECK-NEXT: {{^}}| | | |-CallExpr // CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' // CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' // CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' @@ -101,368 +95,368 @@ void caller_2() { foo(0, 0); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] -// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' -// CHECK: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' void caller_3(int *__counted_by_or_null(len) p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| |-DeclStmt -// CHECK: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= -1' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] -// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_9]] -// CHECK: {{^}}| | `-UnaryOperator {{.+}} prefix '-' -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 1 -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= -1' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] +// CHECK-NEXT: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_9]] +// CHECK-NEXT: {{^}}| | `-UnaryOperator {{.+}} prefix '-' +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 1 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' void caller_4() { int i = 0; foo(&i, -1); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| |-DeclStmt -// CHECK: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= 2' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] -// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_11]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 2 -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= __builtin_get_pointer_upper_bound(&i) - &i && 0 <= 2' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] +// CHECK-NEXT: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_11]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' void caller_5() { int i = 0; foo(&i, 2); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __counted_by(len)':'int *__single' -// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] -// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' -// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' -// CHECK: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(len)':'int *__single' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __counted_by(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' void caller_6(int *__counted_by(len) p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_17]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_17]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' void caller_7(int *__bidi_indexable p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_19]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_19]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' void caller_8(int *__single p, int len) { foo(p, len); } @@ -474,133 +468,168 @@ void caller_8(int *__single p, int len) { void bar(int *__counted_by(*len) *out, int *len); // CHECK: {{^}}|-FunctionDecl [[func_caller_9:0x[^ ]+]] {{.+}} caller_9 -// CHECK: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-CallExpr -// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __counted_by(*len)*__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_21]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __counted_by(*len)*__single' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-CallExpr +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_21]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __counted_by(*len)*__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' void caller_9(int *__counted_by(*len) *out, int *len){ bar(out, len); } -// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 -// CHECK: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] -// CHECK: {{^}} `-CompoundStmt -// CHECK: {{^}} |-DeclStmt -// CHECK: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] -// CHECK: {{^}} | `-DependerDeclsAttr -// CHECK: {{^}} |-DeclStmt -// CHECK: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | |-CallExpr -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' -// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] -// CHECK: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_23]] -// CHECK: {{^}} | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' '=' -// CHECK: {{^}} | | | |-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} lower -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}} | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} upper -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] -// CHECK: {{^}} | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | |-BinaryOperator {{.+}} 'int *' '+' -// CHECK: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' -// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25]] -// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_26]] -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] -// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_len_7]] -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BinaryOperator {{.+}} 'int' '=' -// CHECK: {{^}} | | |-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} `-ReturnStmt -// CHECK: {{^}} `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' -// CHECK: {{^}} `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_28:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *' '+' -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_29:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_28]] -// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_29]] -// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} |-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' -// CHECK: {{^}} `-OpaqueValueExpr [[ove_29]] {{.*}} 'int' +// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] +// CHECK-NEXT: {{^}} `-CompoundStmt +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] +// CHECK-NEXT: {{^}} | `-DependerDeclsAttr +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-CallExpr +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __counted_by(*len)*__single, int *__single)' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __counted_by(*len)*__single' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] +// CHECK-NEXT: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_23]] +// CHECK-NEXT: {{^}} | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __counted_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' '=' +// CHECK-NEXT: {{^}} | | | |-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}} | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] +// CHECK-NEXT: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK-NEXT: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25]] +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_26]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] +// CHECK-NEXT: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | `-DeclRefExpr {{.+}} [[var_len_7]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '=' +// CHECK-NEXT: {{^}} | | |-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} `-ReturnStmt +// CHECK-NEXT: {{^}} `-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= __builtin_get_pointer_upper_bound(p) - p && 0 <= len' +// CHECK-NEXT: {{^}} |-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_28:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_29:0x[^ ]+]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_30:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}} | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_31:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_31]] {{.*}} 'int' +// CHECK: {{^}} |-OpaqueValueExpr [[ove_28]] +// CHECK-NEXT: {{^}} | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | |-OpaqueValueExpr [[ove_29]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'int *' '+' +// CHECK-NEXT: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_29]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_30]] {{.*}} 'int' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_29]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_30]] +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_29]] {{.*}} 'int *__single __counted_by_or_null(count)':'int *__single' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_30]] {{.*}} 'int' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_31]] +// CHECK-NEXT: {{^}} `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} `-DeclRefExpr {{.+}} [[var_len_7]] int *__counted_by_or_null(len) caller_10(int len) { int count; int *__counted_by_or_null(count) p; diff --git a/clang/test/BoundsSafety/AST/ended_by_const_param.c b/clang/test/BoundsSafety/AST/ended_by_const_param.c index d0a5d1b4ab7e0..4e9455c72e865 100644 --- a/clang/test/BoundsSafety/AST/ended_by_const_param.c +++ b/clang/test/BoundsSafety/AST/ended_by_const_param.c @@ -1,5 +1,4 @@ // FileCheck lines automatically generated using make-ast-dump-check-v2.py - // RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety %s 2>&1 | FileCheck %s // RUN: %clang_cc1 -triple x86_64-apple-mac -ast-dump -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s 2>&1 | FileCheck %s #include @@ -31,7 +30,7 @@ void foo(int * const __ended_by(end) start, int* const end) { // CHECK-NEXT: | `-VarDecl {{.+}} used arr 'int[40]' // CHECK-NEXT: `-MaterializeSequenceExpr {{.+}} 'void' // CHECK-NEXT: |-MaterializeSequenceExpr {{.+}} 'void' -// CHECK-NEXT: | |-BoundsCheckExpr {{.+}} 'void' 'arr + 40 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 40' +// CHECK-NEXT: | |-BoundsCheckExpr {{.+}} 'void' 'arr + 40 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 40 && __builtin_get_pointer_lower_bound(arr) <= arr' // CHECK-NEXT: | | |-CallExpr {{.+}} 'void' // CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' // CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'void (int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' Function {{.+}} 'foo' 'void (int *__single __ended_by(end)const, int *__single /* __started_by(start) */ const)' @@ -46,29 +45,40 @@ void foo(int * const __ended_by(end) start, int* const end) { // CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' // CHECK-NEXT: | | | `-IntegerLiteral {{.+}} 'int' 40 // CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK-NEXT: | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK-NEXT: | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK-NEXT: | | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' -// CHECK-NEXT: | | | | `-IntegerLiteral {{.+}} 'int' 40 -// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK-NEXT: | | | `-GetBoundExpr {{.+}} 'int *__bidi_indexable' upper +// CHECK-NEXT: | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | | | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | | `-GetBoundExpr {{.+}} 'int *__bidi_indexable' upper +// CHECK-NEXT: | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: | | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *' // CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-IntegerLiteral {{.+}} 'int' 40 // CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int' '<=' // CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' +// CHECK-NEXT: | | | `-GetBoundExpr {{.+}} 'int *__bidi_indexable' lower +// CHECK-NEXT: | | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int *' // CHECK-NEXT: | | `-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' -// CHECK-NEXT: | | `-IntegerLiteral {{.+}} 'int' 40 +// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' // CHECK-NEXT: | |-OpaqueValueExpr {{.+}} 'int *__bidi_indexable' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int[40]' lvalue Var {{.+}} 'arr' 'int[40]' diff --git a/clang/test/BoundsSafety/AST/ended_by_returns.c b/clang/test/BoundsSafety/AST/ended_by_returns.c index f890139dc74ae..24a1f6cee453c 100644 --- a/clang/test/BoundsSafety/AST/ended_by_returns.c +++ b/clang/test/BoundsSafety/AST/ended_by_returns.c @@ -4,490 +4,559 @@ #include +// CHECK: {{^}}|-FunctionDecl [[func_chunk:0x[^ ]+]] {{.+}} chunk +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_begin:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_end:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-BoundsCheckExpr {{.+}} 'end <= __builtin_get_pointer_upper_bound(begin + 1) && begin + 1 <= end && __builtin_get_pointer_lower_bound(begin + 1) <= begin + 1' +// CHECK-NEXT: {{^}}| |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | `-BinaryOperator {{.+}} 'char *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | |-DeclRefExpr {{.+}} [[var_begin]] +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_end]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_begin]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 1 +// CHECK-NEXT: {{^}}| `-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| `-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| |-DeclRefExpr {{.+}} [[var_end]] +// CHECK-NEXT: {{^}}| |-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_end]] +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_begin]] char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { return begin + 1; } -//CHECK: FunctionDecl [[func_chunk:0x[^ ]+]] {{.*}} used chunk 'char *__single __ended_by(end)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -//CHECK: |-ParmVarDecl [[var_begin:0x[^ ]+]] {{.*}} 'char *__single __ended_by(end)':'char *__single' -//CHECK: |-ParmVarDecl [[var_end:0x[^ ]+]] {{.*}} 'char *__single /* __started_by(begin) */ ':'char *__single' -//CHECK: `-CompoundStmt -//CHECK: `-ReturnStmt -//CHECK: `-ImplicitCastExpr {{.*}} 'char *__single __ended_by(end)':'char *__single' -//CHECK: `-BinaryOperator {{.*}} 'char *__bidi_indexable' '+' -//CHECK: |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -//CHECK: | |-DeclRefExpr {{.+}} [[var_begin]] -//CHECK: | |-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -//CHECK: | | `-DeclRefExpr {{.+}} [[var_end]] -//CHECK: | `-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -//CHECK: | `-DeclRefExpr {{.+}} [[var_begin]] -//CHECK: `-IntegerLiteral {{.*}} 'int' 1 -// CHECK-LABEL: foo +// CHECK: {{^}}|-FunctionDecl [[func_foo:0x[^ ]+]] {{.+}} foo +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_arr:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DeclStmt +// CHECK-NEXT: {{^}}| `-VarDecl [[var_p:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}}| | | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}}| | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' void foo(void) { int arr[10]; int *p = chunk(arr, arr+10); } -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr:0x[^ ]+]] -// CHECK: `-DeclStmt -// CHECK: `-VarDecl [[var_p:0x[^ ]+]] -// CHECK: `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | |-BoundsCheckExpr -// CHECK: | | | |-CallExpr -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr]] -// CHECK: | `-OpaqueValueExpr [[ove_1]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr]] -// CHECK: | `-IntegerLiteral {{.+}} 10 -// CHECK: |-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__bidi_indexable' -// CHECK-LABEL: fooCast +// CHECK: {{^}}|-FunctionDecl [[func_fooCast:0x[^ ]+]] {{.+}} fooCast +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_arr_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DeclStmt +// CHECK-NEXT: {{^}}| `-VarDecl [[var_p_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}}| | | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}}| | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_5]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr_1]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' void fooCast(void) { int arr[10]; int *p = (int*)chunk(arr, arr+10); } -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr_1:0x[^ ]+]] -// CHECK: `-DeclStmt -// CHECK: `-VarDecl [[var_p_1:0x[^ ]+]] -// CHECK: `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | |-BoundsCheckExpr -// CHECK: | | | |-CallExpr -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | |-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_2]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_1]] -// CHECK: | `-OpaqueValueExpr [[ove_3]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_1]] -// CHECK: | `-IntegerLiteral {{.+}} 10 -// CHECK: |-OpaqueValueExpr [[ove_2]] {{.*}} 'char *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_3]] {{.*}} 'char *__bidi_indexable' struct DataWithEndedBy { int *__ended_by(fend) fbegin; int *fend; }; -// CHECK-LABEL: bar +// CHECK: {{^}}|-FunctionDecl [[func_bar:0x[^ ]+]] {{.+}} bar +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_data:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_arr_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(chunk(arr, arr + 10)) && chunk(arr, arr + 10) <= arr + 10 && __builtin_get_pointer_lower_bound(chunk(arr, arr + 10)) <= chunk(arr, arr + 10)' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' +// CHECK-NEXT: {{^}}| | | | |-MemberExpr {{.+}} ->fbegin +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_data]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_6]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}}| | | | | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}}| | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_7]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_9]] +// CHECK-NEXT: {{^}}| | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr_2]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' +// CHECK-NEXT: {{^}}| | |-MemberExpr {{.+}} ->fend +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_data]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_6]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int *__bidi_indexable' void bar(struct DataWithEndedBy *data) { int arr[10]; data->fbegin = chunk(arr, arr+10); data->fend = arr+10; } -// CHECK: |-ParmVarDecl [[var_data:0x[^ ]+]] -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr_2:0x[^ ]+]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsCheckExpr -// CHECK: | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' -// CHECK: | | | |-MemberExpr {{.+}} ->fbegin -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-GetBoundExpr {{.+}} lower -// CHECK: | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_4]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-BoundsCheckExpr -// CHECK: | | | | | |-CallExpr -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_5]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] -// CHECK: | | | `-OpaqueValueExpr [[ove_6]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_2]] -// CHECK: | | | `-IntegerLiteral {{.+}} 10 -// CHECK: | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | `-OpaqueValueExpr [[ove_7]] -// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_2]] -// CHECK: | `-IntegerLiteral {{.+}} 10 -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' -// CHECK: | |-MemberExpr {{.+}} ->fend -// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_data]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' -// CHECK: | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' -// CHECK: |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_7]] {{.*}} 'int *__bidi_indexable' -// CHECK-LABEL: barCast +// CHECK: {{^}}|-FunctionDecl [[func_barCast:0x[^ ]+]] {{.+}} barCast +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_data_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_arr_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound((int *)chunk(arr, arr + 10)) && (int *)chunk(arr, arr + 10) <= arr + 10 && __builtin_get_pointer_lower_bound((int *)chunk(arr, arr + 10)) <= (int *)chunk(arr, arr + 10)' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' +// CHECK-NEXT: {{^}}| | | | |-MemberExpr {{.+}} ->fbegin +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_data_1]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] +// CHECK-NEXT: {{^}}| | | `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}}| | | | | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}}| | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_11]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_11]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_13]] +// CHECK-NEXT: {{^}}| | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_arr_3]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' +// CHECK-NEXT: {{^}}| | |-MemberExpr {{.+}} ->fend +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_data_1]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__bidi_indexable' void barCast(struct DataWithEndedBy *data) { int arr[10]; data->fbegin = (int*)chunk(arr, arr+10); data->fend = arr+10; } -// CHECK: |-ParmVarDecl [[var_data_1:0x[^ ]+]] -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr_3:0x[^ ]+]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsCheckExpr -// CHECK: | | |-BinaryOperator {{.+}} 'int *__single __ended_by(fend)':'int *__single' '=' -// CHECK: | | | |-MemberExpr {{.+}} ->fbegin -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_1]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *__single __ended_by(fend)':'int *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-GetBoundExpr {{.+}} lower -// CHECK: | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_8]] -// CHECK: | | `-CStyleCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-BoundsCheckExpr -// CHECK: | | | | | |-CallExpr -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_9]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] -// CHECK: | | | `-OpaqueValueExpr [[ove_10]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_3]] -// CHECK: | | | `-IntegerLiteral {{.+}} 10 -// CHECK: | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'char *__bidi_indexable' -// CHECK: | `-OpaqueValueExpr [[ove_11]] -// CHECK: | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_arr_3]] -// CHECK: | `-IntegerLiteral {{.+}} 10 -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-BinaryOperator {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' '=' -// CHECK: | |-MemberExpr {{.+}} ->fend -// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithEndedBy *__single' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_1]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'int *__single /* __started_by(fbegin) */ ':'int *__single' -// CHECK: | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' -// CHECK: |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_11]] {{.*}} 'int *__bidi_indexable' struct DataWithCountedBy { long *__counted_by(count) ptr; unsigned long long count; }; -// CHECK-LABEL: baz 'void (struct DataWithCountedBy *__single, int)' +// CHECK: {{^}}|-FunctionDecl [[func_baz:0x[^ ]+]] {{.+}} baz +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_data_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_arr_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'chunk(arr, arr + 10) <= __builtin_get_pointer_upper_bound(chunk(arr, arr + 10)) && __builtin_get_pointer_lower_bound(chunk(arr, arr + 10)) <= chunk(arr, arr + 10) && len <= __builtin_get_pointer_upper_bound(chunk(arr, arr + 10)) - chunk(arr, arr + 10)' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' +// CHECK-NEXT: {{^}}| | | | |-MemberExpr {{.+}} ->ptr +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_data_2]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'unsigned long long' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_14]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'long *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}}| | | | | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}}| | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_15]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] +// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_15]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_17]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len]] +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-BinaryOperator {{.+}} 'unsigned long long' '=' +// CHECK-NEXT: {{^}}| | |-MemberExpr {{.+}} ->count +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_data_2]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_17]] {{.*}} 'unsigned long long' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_14]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'unsigned long long' void baz(struct DataWithCountedBy *data, int len) { int arr[10]; data->ptr = chunk(arr, arr+10); data->count = len; } -// CHECK: |-ParmVarDecl [[var_data_2:0x[^ ]+]] -// CHECK: |-ParmVarDecl [[var_len:0x[^ ]+]] -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr_4:0x[^ ]+]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsCheckExpr -// CHECK: | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' -// CHECK: | | | |-MemberExpr {{.+}} ->ptr -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_2]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-GetBoundExpr {{.+}} lower -// CHECK: | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'unsigned long long' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long long' -// CHECK: | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: | | |-GetBoundExpr {{.+}} upper -// CHECK: | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_12]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-BoundsCheckExpr -// CHECK: | | | | | |-CallExpr -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_13]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] -// CHECK: | | | `-OpaqueValueExpr [[ove_14]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_4]] -// CHECK: | | | `-IntegerLiteral {{.+}} 10 -// CHECK: | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'char *__bidi_indexable' -// CHECK: | `-OpaqueValueExpr [[ove_15]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long long' -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_len]] -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-BinaryOperator {{.+}} 'unsigned long long' '=' -// CHECK: | |-MemberExpr {{.+}} ->count -// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_2]] -// CHECK: | `-OpaqueValueExpr [[ove_15]] {{.*}} 'unsigned long long' -// CHECK: |-OpaqueValueExpr [[ove_12]] {{.*}} 'long *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_15]] {{.*}} 'unsigned long long' -// CHECK-LABEL: bazCast 'void (struct DataWithCountedBy *__single, int)' +// CHECK: {{^}}`-FunctionDecl [[func_bazCast:0x[^ ]+]] {{.+}} bazCast +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_data_3:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK-NEXT: {{^}} `-CompoundStmt +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_arr_5:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-BoundsCheckExpr {{.+}} '(long *)chunk(arr, arr + 10) <= __builtin_get_pointer_upper_bound((long *)chunk(arr, arr + 10)) && __builtin_get_pointer_lower_bound((long *)chunk(arr, arr + 10)) <= (long *)chunk(arr, arr + 10) && len <= __builtin_get_pointer_upper_bound((long *)chunk(arr, arr + 10)) - (long *)chunk(arr, arr + 10)' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' +// CHECK-NEXT: {{^}} | | | |-MemberExpr {{.+}} ->ptr +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_data_3]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | | | | | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | | | `-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'unsigned long long' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK-NEXT: {{^}} | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'long *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} | |-OpaqueValueExpr [[ove_18]] +// CHECK-NEXT: {{^}} | | `-CStyleCastExpr {{.+}} 'long *__bidi_indexable' +// CHECK-NEXT: {{^}} | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | |-BoundsCheckExpr {{.+}} 'arr + 10 <= __builtin_get_pointer_upper_bound(arr) && arr <= arr + 10 && __builtin_get_pointer_lower_bound(arr) <= arr' +// CHECK-NEXT: {{^}} | | | | | |-CallExpr +// CHECK-NEXT: {{^}} | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' +// CHECK-NEXT: {{^}} | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] +// CHECK-NEXT: {{^}} | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' +// CHECK-NEXT: {{^}} | | | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_20]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | | | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | | | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | | | `-OpaqueValueExpr [[ove_20]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_20]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | | |-OpaqueValueExpr [[ove_20]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_19]] +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_20]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] +// CHECK-NEXT: {{^}} | | | `-IntegerLiteral {{.+}} 10 +// CHECK-NEXT: {{^}} | | |-OpaqueValueExpr [[ove_19]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_20]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_21]] +// CHECK-NEXT: {{^}} | `-ImplicitCastExpr {{.+}} 'unsigned long long' +// CHECK-NEXT: {{^}} | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK-NEXT: {{^}} `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} |-BinaryOperator {{.+}} 'unsigned long long' '=' +// CHECK-NEXT: {{^}} | |-MemberExpr {{.+}} ->count +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_data_3]] +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_21]] {{.*}} 'unsigned long long' +// CHECK: {{^}} |-OpaqueValueExpr [[ove_18]] {{.*}} 'long *__bidi_indexable' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_21]] {{.*}} 'unsigned long long' void bazCast(struct DataWithCountedBy *data, int len) { int arr[10]; data->ptr = (long*)chunk(arr, arr+10); data->count = len; } -// CHECK: |-ParmVarDecl [[var_data_3:0x[^ ]+]] -// CHECK: |-ParmVarDecl [[var_len_1:0x[^ ]+]] -// CHECK: `-CompoundStmt -// CHECK: |-DeclStmt -// CHECK: | `-VarDecl [[var_arr_5:0x[^ ]+]] -// CHECK: |-MaterializeSequenceExpr {{.+}} -// CHECK: | |-BoundsCheckExpr -// CHECK: | | |-BinaryOperator {{.+}} 'long *__single __counted_by(count)':'long *__single' '=' -// CHECK: | | | |-MemberExpr {{.+}} ->ptr -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_data_3]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *__single __counted_by(count)':'long *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-GetBoundExpr {{.+}} lower -// CHECK: | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'unsigned long long' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'unsigned long long' -// CHECK: | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: | | |-GetBoundExpr {{.+}} upper -// CHECK: | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | | `-ImplicitCastExpr {{.+}} 'long *' -// CHECK: | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_16]] -// CHECK: | | `-CStyleCastExpr {{.+}} 'long *__bidi_indexable' -// CHECK: | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | |-BoundsCheckExpr -// CHECK: | | | | | |-CallExpr -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)(*__single)(char *__single __ended_by(end), char *__single /* __started_by(begin) */ )' -// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[func_chunk]] -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *__single __ended_by(end)':'char *__single' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *__single /* __started_by(begin) */ ':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_17]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] -// CHECK: | | | `-OpaqueValueExpr [[ove_18]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int *__bidi_indexable' '+' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_arr_5]] -// CHECK: | | | `-IntegerLiteral {{.+}} 10 -// CHECK: | | |-OpaqueValueExpr [[ove_17]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'char *__bidi_indexable' -// CHECK: | `-OpaqueValueExpr [[ove_19]] -// CHECK: | `-ImplicitCastExpr {{.+}} 'unsigned long long' -// CHECK: | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | `-DeclRefExpr {{.+}} [[var_len_1]] -// CHECK: `-MaterializeSequenceExpr {{.+}} -// CHECK: |-BinaryOperator {{.+}} 'unsigned long long' '=' -// CHECK: | |-MemberExpr {{.+}} ->count -// CHECK: | | `-ImplicitCastExpr {{.+}} 'struct DataWithCountedBy *__single' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_data_3]] -// CHECK: | `-OpaqueValueExpr [[ove_19]] {{.*}} 'unsigned long long' -// CHECK: |-OpaqueValueExpr [[ove_16]] {{.*}} 'long *__bidi_indexable' -// CHECK: `-OpaqueValueExpr [[ove_19]] {{.*}} 'unsigned long long' diff --git a/clang/test/BoundsSafety/AST/sized_by_or_null_call.c b/clang/test/BoundsSafety/AST/sized_by_or_null_call.c index 0cc509903787a..ac4db157d3e47 100644 --- a/clang/test/BoundsSafety/AST/sized_by_or_null_call.c +++ b/clang/test/BoundsSafety/AST/sized_by_or_null_call.c @@ -4,11 +4,11 @@ #include -// CHECK: {{^}}|-FunctionDecl [[func_foo:0x[^ ]+]] {{.+}} foo -// CHECK: {{^}}| |-ParmVarDecl [[var_p:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt +// CHECK: {{^}}|-FunctionDecl [[func_foo:0x[^ ]+]] {{.+}} foo +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt void foo(int *__sized_by_or_null(len) p, int len) {} // CHECK: {{^}}|-FunctionDecl [[func_caller_1:0x[^ ]+]] {{.+}} caller_1 @@ -19,12 +19,9 @@ void foo(int *__sized_by_or_null(len) p, int len) {} // CHECK-NEXT: {{^}}| | | |-CallExpr // CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' // CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 2 -// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' // CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' @@ -66,12 +63,9 @@ void caller_1() { // CHECK-NEXT: {{^}}| | | |-CallExpr // CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' // CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK-NEXT: {{^}}| | | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] -// CHECK-NEXT: {{^}}| | | | `-IntegerLiteral {{.+}} 0 -// CHECK-NEXT: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' // CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' // CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_2]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' @@ -105,534 +99,503 @@ void caller_2() { foo(0, 0); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] -// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_3:0x[^ ]+]] {{.+}} caller_3 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_4]] +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_5]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_1]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_6]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_5]] {{.*}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_7]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_1]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_4]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_7]] {{.*}} 'int' void caller_3(int *__sized_by_or_null(len) p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| |-DeclStmt -// CHECK: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= -1' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] -// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_9]] -// CHECK: {{^}}| | `-UnaryOperator {{.+}} prefix '-' -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 1 -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_4:0x[^ ]+]] {{.+}} caller_4 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_i:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || -1 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= -1' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_8]] +// CHECK-NEXT: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_9]] +// CHECK-NEXT: {{^}}| | `-UnaryOperator {{.+}} prefix '-' +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 1 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_8]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' void caller_4() { int i = 0; foo(&i, -1); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| |-DeclStmt -// CHECK: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= 2' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] -// CHECK: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_11]] -// CHECK: {{^}}| | `-IntegerLiteral {{.+}} 2 -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_5:0x[^ ]+]] {{.+}} caller_5 +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| |-DeclStmt +// CHECK-NEXT: {{^}}| | `-VarDecl [[var_i_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} '&i <= __builtin_get_pointer_upper_bound(&i) && __builtin_get_pointer_lower_bound(&i) <= &i && !&i || 2 <= (char *)__builtin_get_pointer_upper_bound(&i) - (char *)&i && 0 <= 2' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] +// CHECK-NEXT: {{^}}| | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_i_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_11]] +// CHECK-NEXT: {{^}}| | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_10]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' void caller_5() { int i = 0; foo(&i, 2); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __sized_by(len)':'int *__single' -// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] -// CHECK: {{^}}| | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(len)':'int *__single' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_6:0x[^ ]+]] {{.+}} caller_6 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_13:0x[^ ]+]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_14:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_15:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_12]] +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_13]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_p_2]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_14]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_13]] {{.*}} 'int *__single __sized_by(len)':'int *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_14]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_15]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_2]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_12]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_15]] {{.*}} 'int' void caller_6(int *__sized_by(len) p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_17]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_7:0x[^ ]+]] {{.+}} caller_7 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_17:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_16]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_3]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_17]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_3]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_16]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_17]] {{.*}} 'int' void caller_7(int *__bidi_indexable p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 -// CHECK: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' -// CHECK: {{^}}| | | |-CallExpr -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' -// CHECK: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] -// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} lower -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' -// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}}| | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__single' -// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}}| | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_19]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_caller_8:0x[^ ]+]] {{.+}} caller_8 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_p_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_4:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *)p && 0 <= len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by_or_null(len), int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_foo]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_18:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_19:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}}| | | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | | `-CStyleCastExpr {{.+}} 'char *__single' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_18]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_p_4]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_19]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_4]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_18]] {{.*}} 'int *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_19]] {{.*}} 'int' void caller_8(int *__single p, int len) { foo(p, len); } -// CHECK: {{^}}|-FunctionDecl [[func_bar:0x[^ ]+]] {{.+}} bar -// CHECK: {{^}}| |-ParmVarDecl [[var_out:0x[^ ]+]] -// CHECK: {{^}}| `-ParmVarDecl [[var_len_5:0x[^ ]+]] -// CHECK: {{^}}| `-DependerDeclsAttr +// CHECK: {{^}}|-FunctionDecl [[func_bar:0x[^ ]+]] {{.+}} bar +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_out:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len_5:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DependerDeclsAttr void bar(int *__sized_by(*len) *out, int *len); -// CHECK: {{^}}|-FunctionDecl [[func_caller_9:0x[^ ]+]] {{.+}} caller_9 -// CHECK: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] -// CHECK: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] -// CHECK: {{^}}| | `-DependerDeclsAttr -// CHECK: {{^}}| `-CompoundStmt -// CHECK: {{^}}| `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}}| | |-CallExpr -// CHECK: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' -// CHECK: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] -// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __sized_by(*len)*__single' -// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' -// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] -// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' -// CHECK: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] -// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_21]] -// CHECK: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] -// CHECK: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __sized_by(*len)*__single' -// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_caller_9:0x[^ ]+]] {{.+}} caller_9 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_out_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_6:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-CallExpr +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_20:0x[^ ]+]] {{.*}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_21:0x[^ ]+]] {{.*}} 'int *__single' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_20]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_out_1]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_21]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_len_6]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove_20]] {{.*}} 'int *__single __sized_by(*len)*__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_21]] {{.*}} 'int *__single' void caller_9(int *__sized_by(*len) *out, int *len){ bar(out, len); } -// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 -// CHECK: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] -// CHECK: {{^}} `-CompoundStmt -// CHECK: {{^}} |-DeclStmt -// CHECK: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] -// CHECK: {{^}} | `-DependerDeclsAttr -// CHECK: {{^}} |-DeclStmt -// CHECK: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | |-CallExpr -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' -// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] -// CHECK: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_23]] -// CHECK: {{^}} | | `-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *__bidi_indexable)p && 0 <= len' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' '=' -// CHECK: {{^}} | | | |-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | |-GetBoundExpr {{.+}} lower -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '||' -// CHECK: {{^}} | | |-UnaryOperator {{.+}} cannot overflow -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: {{^}} | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: {{^}} | | | | `-GetBoundExpr {{.+}} upper -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: {{^}} | | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: {{^}} | | |-IntegerLiteral {{.+}} 0 -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] -// CHECK: {{^}} | | `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}} | | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: {{^}} | | | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: {{^}} | | | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' -// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25]] -// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_26]] -// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | | | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] -// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_len_7]] -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BinaryOperator {{.+}} 'int' '=' -// CHECK: {{^}} | | |-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} | | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' -// CHECK: {{^}} `-ReturnStmt -// CHECK: {{^}} `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' -// CHECK: {{^}} `-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} |-MaterializeSequenceExpr {{.+}} -// CHECK: {{^}} | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' -// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_28:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | |-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | `-BinaryOperator {{.+}} 'char *' '+' -// CHECK: {{^}} | | | |-CStyleCastExpr {{.+}} 'char *' -// CHECK: {{^}} | | | | `-ImplicitCastExpr {{.+}} 'int *' -// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | | `-OpaqueValueExpr [[ove_29:0x[^ ]+]] {{.*}} 'int' -// CHECK: {{^}} | |-OpaqueValueExpr [[ove_28]] -// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} | | `-DeclRefExpr {{.+}} [[var_p_5]] -// CHECK: {{^}} | `-OpaqueValueExpr [[ove_29]] -// CHECK: {{^}} | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: {{^}} | `-DeclRefExpr {{.+}} [[var_count]] -// CHECK: {{^}} |-OpaqueValueExpr [[ove_28]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' -// CHECK: {{^}} `-OpaqueValueExpr [[ove_29]] {{.*}} 'int' +// CHECK: {{^}}`-FunctionDecl [[func_caller_10:0x[^ ]+]] {{.+}} caller_10 +// CHECK-NEXT: {{^}} |-ParmVarDecl [[var_len_7:0x[^ ]+]] +// CHECK-NEXT: {{^}} `-CompoundStmt +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_count:0x[^ ]+]] +// CHECK-NEXT: {{^}} | `-DependerDeclsAttr +// CHECK-NEXT: {{^}} |-DeclStmt +// CHECK-NEXT: {{^}} | `-VarDecl [[var_p_5:0x[^ ]+]] +// CHECK-NEXT: {{^}} |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-CallExpr +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'void (*__single)(int *__single __sized_by(*len)*__single, int *__single)' +// CHECK-NEXT: {{^}} | | | | `-DeclRefExpr {{.+}} [[func_bar]] +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *__single __sized_by(*len)*__single' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_22:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_23:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_22]] +// CHECK-NEXT: {{^}} | | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_23]] +// CHECK-NEXT: {{^}} | | `-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_22]] {{.*}} 'int *__single __sized_by_or_null(count)*__bidi_indexable' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_23]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} `-ReturnStmt +// CHECK-NEXT: {{^}} `-BoundsCheckExpr {{.+}} 'p <= __builtin_get_pointer_upper_bound(p) && __builtin_get_pointer_lower_bound(p) <= p && !p || len <= (char *)__builtin_get_pointer_upper_bound(p) - (char *__bidi_indexable)p && 0 <= len' +// CHECK-NEXT: {{^}} |-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(len)':'int *__single' +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_24:0x[^ ]+]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | |-OpaqueValueExpr [[ove_25:0x[^ ]+]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_26:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '||' +// CHECK-NEXT: {{^}} | |-UnaryOperator {{.+}} cannot overflow +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}} | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_27:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}} | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}} | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}} | | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | `-CStyleCastExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_24]] {{.*}} 'int *__bidi_indexable' +// CHECK: {{^}} | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}} | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}} | `-OpaqueValueExpr [[ove_27]] {{.*}} 'int' +// CHECK: {{^}} |-OpaqueValueExpr [[ove_24]] +// CHECK-NEXT: {{^}} | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}} | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'int *__bidi_indexable' +// CHECK-NEXT: {{^}} | | | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | |-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | `-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}} | | | | |-CStyleCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}} | | | | | `-ImplicitCastExpr {{.+}} 'int *' +// CHECK-NEXT: {{^}} | | | | | `-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | | | | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} | | |-OpaqueValueExpr [[ove_25]] +// CHECK-NEXT: {{^}} | | | `-ImplicitCastExpr {{.+}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK-NEXT: {{^}} | | | `-DeclRefExpr {{.+}} [[var_p_5]] +// CHECK-NEXT: {{^}} | | `-OpaqueValueExpr [[ove_26]] +// CHECK-NEXT: {{^}} | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} | | `-DeclRefExpr {{.+}} [[var_count]] +// CHECK-NEXT: {{^}} | |-OpaqueValueExpr [[ove_25]] {{.*}} 'int *__single __sized_by_or_null(count)':'int *__single' +// CHECK: {{^}} | `-OpaqueValueExpr [[ove_26]] {{.*}} 'int' +// CHECK: {{^}} `-OpaqueValueExpr [[ove_27]] +// CHECK-NEXT: {{^}} `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}} `-DeclRefExpr {{.+}} [[var_len_7]] int *__sized_by_or_null(len) caller_10(int len) { int count; int *__sized_by_or_null(count) p; bar(&p, &count); - p = p; // workaround for missing return bounds check - count = len; return p; } - diff --git a/clang/test/BoundsSafety/AST/unify-function-types.c b/clang/test/BoundsSafety/AST/unify-function-types.c index f5f6fd7bcf1a6..9a67757963d7c 100644 --- a/clang/test/BoundsSafety/AST/unify-function-types.c +++ b/clang/test/BoundsSafety/AST/unify-function-types.c @@ -1,5 +1,3 @@ - - // RUN: %clang_cc1 -ast-dump -fbounds-safety -verify=c %s | FileCheck %s // RUN: %clang_cc1 -x c++ -ast-dump -fbounds-safety -fbounds-attributes-cxx-experimental -verify=cpp %s #include @@ -8,109 +6,109 @@ char funcA(char buf[__counted_by(len)], int len, int len2); char funcB(char arr[__counted_by(size)], int size, int size2); char funcC(char arr[__counted_by(size2)], int size, int size2); -// CHECK: TranslationUnitDecl -// CHECK: |-FunctionDecl [[func_funcA:0x[^ ]+]] {{.+}} funcA -// CHECK: | |-ParmVarDecl [[var_buf:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_len:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | `-ParmVarDecl [[var_len2:0x[^ ]+]] -// CHECK: |-FunctionDecl [[func_funcB:0x[^ ]+]] {{.+}} funcB -// CHECK: | |-ParmVarDecl [[var_arr:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | `-ParmVarDecl [[var_size2:0x[^ ]+]] -// CHECK: |-FunctionDecl [[func_funcC:0x[^ ]+]] {{.+}} funcC -// CHECK: | |-ParmVarDecl [[var_arr_1:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size_1:0x[^ ]+]] -// CHECK: | `-ParmVarDecl [[var_size2_1:0x[^ ]+]] -// CHECK: | `-DependerDeclsAttr +// CHECK: {{^}}TranslationUnitDecl +// CHECK: {{^}}|-FunctionDecl [[func_funcA:0x[^ ]+]] {{.+}} funcA +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_buf:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len2:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_funcB:0x[^ ]+]] {{.+}} funcB +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_arr:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_size2:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_funcC:0x[^ ]+]] {{.+}} funcC +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_arr_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_size2_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-DependerDeclsAttr char test1(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { return (src_len % 2 == 0 ? funcA : funcB)(src_buf, src_len, src_len2); } -// CHECK: |-FunctionDecl [[func_test1:0x[^ ]+]] {{.+}} test1 -// CHECK: | |-ParmVarDecl [[var_src_buf:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_src_len:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | |-ParmVarDecl [[var_src_len2:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | `-ReturnStmt -// CHECK: | `-MaterializeSequenceExpr {{.+}} -// CHECK: | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-BoundsCheckExpr -// CHECK: | | | |-CallExpr -// CHECK: | | | | |-ParenExpr -// CHECK: | | | | | `-ConditionalOperator {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '==' -// CHECK: | | | | | | |-BinaryOperator {{.+}} 'int' '%' -// CHECK: | | | | | | | |-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len]] -// CHECK: | | | | | | | `-IntegerLiteral {{.+}} 2 -// CHECK: | | | | | | `-IntegerLiteral {{.+}} 0 -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' -// CHECK: | | | | | | `-DeclRefExpr {{.+}} [[func_funcA]] -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(size), int, int)' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_funcB]] -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | |-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | | |-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-GetBoundExpr {{.+}} lower -// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' -// CHECK: | | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-IntegerLiteral {{.+}} 0 -// CHECK: | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' -// CHECK: | | |-OpaqueValueExpr [[ove]] -// CHECK: | | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' -// CHECK: | | | | |-OpaqueValueExpr [[ove_1]] -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[var_src_buf]] -// CHECK: | | | | `-OpaqueValueExpr [[ove_2]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_len]] -// CHECK: | | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' -// CHECK: | | |-OpaqueValueExpr [[ove_3]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len]] -// CHECK: | | `-OpaqueValueExpr [[ove_4]] -// CHECK: | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | `-DeclRefExpr {{.+}} [[var_src_len2]] -// CHECK: | |-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_3]] {{.*}} 'int' -// CHECK: | `-OpaqueValueExpr [[ove_4]] {{.*}} 'int' +// CHECK: {{^}}|-FunctionDecl [[func_test1:0x[^ ]+]] {{.+}} test1 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_buf:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_len:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_len2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-BoundsCheckExpr {{.+}} 'src_buf <= __builtin_get_pointer_upper_bound(src_buf) && __builtin_get_pointer_lower_bound(src_buf) <= src_buf && src_len <= __builtin_get_pointer_upper_bound(src_buf) - src_buf && 0 <= src_len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ParenExpr +// CHECK-NEXT: {{^}}| | | | | `-ConditionalOperator {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' +// CHECK-NEXT: {{^}}| | | | | |-BinaryOperator {{.+}} 'int' '==' +// CHECK-NEXT: {{^}}| | | | | | |-BinaryOperator {{.+}} 'int' '%' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK-NEXT: {{^}}| | | | | | | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| | | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(len), int, int)' +// CHECK-NEXT: {{^}}| | | | | | `-DeclRefExpr {{.+}} [[func_funcA]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char (*__single)(char *__single __counted_by(size), int, int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_funcB]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | |-OpaqueValueExpr [[ove_1:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_2:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_3:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_4:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove]] +// CHECK-NEXT: {{^}}| | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_1]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_src_buf]] +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_2]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_1]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | `-OpaqueValueExpr [[ove_2]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_3]] +// CHECK-NEXT: {{^}}| | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | `-DeclRefExpr {{.+}} [[var_src_len]] +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_4]] +// CHECK-NEXT: {{^}}| | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | `-DeclRefExpr {{.+}} [[var_src_len2]] +// CHECK-NEXT: {{^}}| |-OpaqueValueExpr [[ove]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_3]] {{.*}} 'int' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_4]] {{.*}} 'int' char test2(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { @@ -119,124 +117,158 @@ char test2(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { return (src_len % 2 == 0 ? funcA : funcC)(src_buf, src_len, src_len2); } +// No FileCheck lines for `test2` because it contains errors. + char * __counted_by(len) funcD(char buf[__counted_by(len)], int len, int len2); char * __counted_by(size) funcE(char arr[__counted_by(size)], int size, int size2); char * __counted_by(size2) funcF(char arr[__counted_by(size)], int size, int size2); -// CHECK: |-FunctionDecl [[func_funcD:0x[^ ]+]] {{.+}} funcD -// CHECK: | |-ParmVarDecl [[var_buf_1:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_len_1:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | `-ParmVarDecl [[var_len2_1:0x[^ ]+]] -// CHECK: |-FunctionDecl [[func_funcE:0x[^ ]+]] {{.+}} funcE -// CHECK: | |-ParmVarDecl [[var_arr_2:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size_2:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | `-ParmVarDecl [[var_size2_2:0x[^ ]+]] -// CHECK: |-FunctionDecl [[func_funcF:0x[^ ]+]] {{.+}} funcF -// CHECK: | |-ParmVarDecl [[var_arr_3:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_size_3:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | `-ParmVarDecl [[var_size2_3:0x[^ ]+]] +// CHECK: {{^}}|-FunctionDecl [[func_funcD:0x[^ ]+]] {{.+}} funcD +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_buf_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_len_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_len2_1:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_funcE:0x[^ ]+]] {{.+}} funcE +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_arr_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_size2_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}|-FunctionDecl [[func_funcF:0x[^ ]+]] {{.+}} funcF +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_arr_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_size_3:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| `-ParmVarDecl [[var_size2_3:0x[^ ]+]] char * __counted_by(src_len) test3(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { return (src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2); } -// CHECK: |-FunctionDecl [[func_test3:0x[^ ]+]] {{.+}} test3 -// CHECK: | |-ParmVarDecl [[var_src_buf_2:0x[^ ]+]] -// CHECK: | |-ParmVarDecl [[var_src_len_2:0x[^ ]+]] -// CHECK: | | `-DependerDeclsAttr -// CHECK: | |-ParmVarDecl [[var_src_len2_2:0x[^ ]+]] -// CHECK: | `-CompoundStmt -// CHECK: | `-ReturnStmt -// CHECK: | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | `-MaterializeSequenceExpr {{.+}} -// CHECK: | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | | | | | |-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | | | | | `-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | | | |-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int' -// CHECK: | | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: | | |-OpaqueValueExpr [[ove_6]] -// CHECK: | | | `-MaterializeSequenceExpr {{.+}} -// CHECK: | | | |-MaterializeSequenceExpr {{.+}} -// CHECK: | | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' -// CHECK: | | | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'char *' '+' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int' -// CHECK: | | | | |-OpaqueValueExpr [[ove_7]] -// CHECK: | | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[var_src_buf_2]] -// CHECK: | | | | `-OpaqueValueExpr [[ove_8]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] -// CHECK: | | | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' -// CHECK: | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'int' -// CHECK: | | |-OpaqueValueExpr [[ove_9]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] -// CHECK: | | |-OpaqueValueExpr [[ove_10]] -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | `-DeclRefExpr {{.+}} [[var_src_len2_2]] -// CHECK: | | `-OpaqueValueExpr [[ove_5]] -// CHECK: | | `-BoundsCheckExpr -// CHECK: | | |-CallExpr -// CHECK: | | | |-ParenExpr -// CHECK: | | | | `-ConditionalOperator {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' -// CHECK: | | | | |-BinaryOperator {{.+}} 'int' '==' -// CHECK: | | | | | |-BinaryOperator {{.+}} 'int' '%' -// CHECK: | | | | | | |-ImplicitCastExpr {{.+}} 'int' -// CHECK: | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] -// CHECK: | | | | | | `-IntegerLiteral {{.+}} 2 -// CHECK: | | | | | `-IntegerLiteral {{.+}} 0 -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' -// CHECK: | | | | | `-DeclRefExpr {{.+}} [[func_funcD]] -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(size)(*__single)(char *__single __counted_by(size), int, int)' -// CHECK: | | | | `-DeclRefExpr {{.+}} [[func_funcE]] -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' -// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | |-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-GetBoundExpr {{.+}} lower -// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '&&' -// CHECK: | | |-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'long' -// CHECK: | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: | | | `-BinaryOperator {{.+}} 'long' '-' -// CHECK: | | | |-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | | `-GetBoundExpr {{.+}} upper -// CHECK: | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | | `-ImplicitCastExpr {{.+}} 'char *' -// CHECK: | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | | `-BinaryOperator {{.+}} 'int' '<=' -// CHECK: | | |-IntegerLiteral {{.+}} 0 -// CHECK: | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: | |-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__bidi_indexable' -// CHECK: | |-OpaqueValueExpr [[ove_9]] {{.*}} 'int' -// CHECK: | |-OpaqueValueExpr [[ove_10]] {{.*}} 'int' -// CHECK: | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}}|-FunctionDecl [[func_test3:0x[^ ]+]] {{.+}} test3 +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_buf_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_len_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| | `-DependerDeclsAttr +// CHECK-NEXT: {{^}}| |-ParmVarDecl [[var_src_len2_2:0x[^ ]+]] +// CHECK-NEXT: {{^}}| `-CompoundStmt +// CHECK-NEXT: {{^}}| `-ReturnStmt +// CHECK-NEXT: {{^}}| `-BoundsCheckExpr {{.+}} '(src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2) <= __builtin_get_pointer_upper_bound((src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2)) && __builtin_get_pointer_lower_bound((src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2)) <= (src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2) && src_len <= __builtin_get_pointer_upper_bound((src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2)) - (src_len % 2 == 0 ? funcD : funcE)(src_buf, src_len, src_len2) && 0 <= src_len' +// CHECK-NEXT: {{^}}| |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_5:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_6:0x[^ ]+]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_7:0x[^ ]+]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | | | | | |-OpaqueValueExpr [[ove_8:0x[^ ]+]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | | | | | | `-OpaqueValueExpr [[ove_9:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | | | |-OpaqueValueExpr [[ove_10:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | | | | `-OpaqueValueExpr [[ove_11:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_12:0x[^ ]+]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | |-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_5]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | `-OpaqueValueExpr [[ove_12]] {{.*}} 'int' +// CHECK: {{^}}| |-OpaqueValueExpr [[ove_5]] +// CHECK-NEXT: {{^}}| | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}}| | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_7]] +// CHECK-NEXT: {{^}}| | | | `-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | |-MaterializeSequenceExpr {{.+}} +// CHECK-NEXT: {{^}}| | | | | |-BoundsSafetyPointerPromotionExpr {{.+}} 'char *__bidi_indexable' +// CHECK-NEXT: {{^}}| | | | | | |-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | | |-BinaryOperator {{.+}} 'char *' '+' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | | | `-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | | | |-OpaqueValueExpr [[ove_8]] +// CHECK-NEXT: {{^}}| | | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | | `-DeclRefExpr {{.+}} [[var_src_buf_2]] +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_9]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK-NEXT: {{^}}| | | | |-OpaqueValueExpr [[ove_8]] {{.*}} 'char *__single __counted_by(src_len)':'char *__single' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_9]] {{.*}} 'int' +// CHECK: {{^}}| | | |-OpaqueValueExpr [[ove_10]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK-NEXT: {{^}}| | | |-OpaqueValueExpr [[ove_11]] +// CHECK-NEXT: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | `-DeclRefExpr {{.+}} [[var_src_len2_2]] +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_6]] +// CHECK-NEXT: {{^}}| | | `-BoundsCheckExpr {{.+}} 'src_buf <= __builtin_get_pointer_upper_bound(src_buf) && __builtin_get_pointer_lower_bound(src_buf) <= src_buf && src_len <= __builtin_get_pointer_upper_bound(src_buf) - src_buf && 0 <= src_len' +// CHECK-NEXT: {{^}}| | | |-CallExpr +// CHECK-NEXT: {{^}}| | | | |-ParenExpr +// CHECK-NEXT: {{^}}| | | | | `-ConditionalOperator {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' +// CHECK-NEXT: {{^}}| | | | | |-BinaryOperator {{.+}} 'int' '==' +// CHECK-NEXT: {{^}}| | | | | | |-BinaryOperator {{.+}} 'int' '%' +// CHECK-NEXT: {{^}}| | | | | | | |-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| | | | | | | | `-DeclRefExpr {{.+}} [[var_src_len_2]] +// CHECK-NEXT: {{^}}| | | | | | | `-IntegerLiteral {{.+}} 2 +// CHECK-NEXT: {{^}}| | | | | | `-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' +// CHECK-NEXT: {{^}}| | | | | | `-DeclRefExpr {{.+}} [[func_funcD]] +// CHECK-NEXT: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *__single __counted_by(size)(*__single)(char *__single __counted_by(size), int, int)' +// CHECK-NEXT: {{^}}| | | | | `-DeclRefExpr {{.+}} [[func_funcE]] +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *__single __counted_by(len)':'char *__single' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | |-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} lower +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '&&' +// CHECK-NEXT: {{^}}| | | |-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'long' +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: {{^}}| | | | `-BinaryOperator {{.+}} 'long' '-' +// CHECK-NEXT: {{^}}| | | | |-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | | `-GetBoundExpr {{.+}} upper +// CHECK-NEXT: {{^}}| | | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | | `-ImplicitCastExpr {{.+}} 'char *' +// CHECK-NEXT: {{^}}| | | | `-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | | `-BinaryOperator {{.+}} 'int' '<=' +// CHECK-NEXT: {{^}}| | | |-IntegerLiteral {{.+}} 0 +// CHECK-NEXT: {{^}}| | | `-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_7]] {{.*}} 'char *__bidi_indexable' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_10]] {{.*}} 'int' +// CHECK: {{^}}| | |-OpaqueValueExpr [[ove_11]] {{.*}} 'int' +// CHECK: {{^}}| | `-OpaqueValueExpr [[ove_6]] {{.*}} 'char *__single __counted_by(len)':'char *__single' +// CHECK: {{^}}| `-OpaqueValueExpr [[ove_12]] +// CHECK-NEXT: {{^}}| `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: {{^}}| `-DeclRefExpr {{.+}} [[var_src_len_2]] + char test4(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { // c-error@+2{{conditional expression evaluates functions with incompatible bound attributes 'char *__single __counted_by(len)(*__single)(char *__single __counted_by(len), int, int)' (aka 'char *__single(*__single)(char *__single, int, int)') and 'char *__single __counted_by(size2)(*__single)(char *__single __counted_by(size), int, int)' (aka 'char *__single(*__single)(char *__single, int, int)')}} @@ -244,6 +276,8 @@ char test4(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { return *(src_len % 2 == 0 ? funcD : funcF)(src_buf, src_len, src_len2); } +// No FileCheck lines for `test4` because it contains errors. + #ifdef __cplusplus char * __counted_by(src_len) test5(char src_buf[__counted_by(src_len)], int src_len, int src_len2) { auto &funcRefD (funcD); diff --git a/clang/test/BoundsSafety/CodeGen/addr-of-array-elem-O2.c b/clang/test/BoundsSafety/CodeGen/addr-of-array-elem-O2.c index a94ffc9b0d1ac..d82541f31b761 100644 --- a/clang/test/BoundsSafety/CodeGen/addr-of-array-elem-O2.c +++ b/clang/test/BoundsSafety/CodeGen/addr-of-array-elem-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -7,26 +6,28 @@ int arr[10]; int v; +// CHECK-LABEL: @main( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @v, align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr @arr, i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[BOUND_PTR_ARITH]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], getelementptr inbounds nuw (i8, ptr @arr, i64 40), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[BOUND_PTR_ARITH]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], @arr, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP4]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF8:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: ret i32 [[TMP5]] +// int main() { int *ptr = &arr[v]; return *ptr; } -// CHECK-LABEL: @v -// CHECK-LABEL: @arr -// CHECK-LABEL: @main( -// CHECK: entry: -// CHECK: [[TMP0:%.*]] = load i32, ptr @v, align 4, {{!tbaa ![0-9]+}} -// CHECK: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 -// CHECK: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr @arr, i64 [[IDXPROM]] -// CHECK: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], getelementptr inbounds nuw (i8, ptr @arr, i64 40), {{!annotation ![0-9]+}} -// CHECK: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], @arr, {{!annotation ![0-9]+}} -// CHECK: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: -// CHECK: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK: unreachable -// CHECK: cont1: -// CHECK: [[TMP3:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} -// CHECK: ret i32 [[TMP3]] // diff --git a/clang/test/BoundsSafety/CodeGen/addr-of-array-elem.c b/clang/test/BoundsSafety/CodeGen/addr-of-array-elem.c index e2cd4b12086c5..cb08147f05c7e 100644 --- a/clang/test/BoundsSafety/CodeGen/addr-of-array-elem.c +++ b/clang/test/BoundsSafety/CodeGen/addr-of-array-elem.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -8,54 +7,61 @@ int arr[10]; int v; // CHECK-LABEL: @main( -// CHECK: entry: -// CHECK: [[RETVAL:%.*]] = alloca i32, align 4 -// CHECK: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK: store i32 0, ptr [[RETVAL]], align 4 -// CHECK: [[TMP0:%.*]] = load i32, ptr @v, align 4 -// CHECK: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK: store ptr @arr, ptr [[TMP1]], align 8 -// CHECK: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK: store ptr getelementptr inbounds (i32, ptr @arr, i64 10), ptr [[TMP2]], align 8 -// CHECK: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK: store ptr @arr, ptr [[TMP3]], align 8 -// CHECK: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 -// CHECK: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 -// CHECK: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 [[IDXPROM]] -// CHECK: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 -// CHECK: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 -// CHECK: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK: store ptr [[TMP8]], ptr [[TMP9]], align 8 -// CHECK: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 -// CHECK: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK: store ptr [[TMP11]], ptr [[TMP12]], align 8 -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: -// CHECK: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK: unreachable -// CHECK: cont: -// CHECK: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap1: -// CHECK: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK: unreachable -// CHECK: cont2: -// CHECK: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK: ret i32 [[TMP15]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @v, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr @arr, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr getelementptr inbounds (i32, ptr @arr, i64 10), ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr @arr, ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP5]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-NEXT: ret i32 [[TMP17]] // int main() { int *ptr = &arr[v]; diff --git a/clang/test/BoundsSafety/CodeGen/addr-of-packed-struct.c b/clang/test/BoundsSafety/CodeGen/addr-of-packed-struct.c index ac2b39b8f29fd..b97b0a6457ba8 100644 --- a/clang/test/BoundsSafety/CodeGen/addr-of-packed-struct.c +++ b/clang/test/BoundsSafety/CodeGen/addr-of-packed-struct.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o /dev/null // RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o /dev/null @@ -15,6 +14,13 @@ struct __attribute__((packed)) foo { // CHECK-LABEL: @p( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[S:%.*]], i64 4 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[S]], i64 8 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT2:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: // CHECK-NEXT: ret ptr [[TMP0]] // unsigned *p(struct foo *s) { diff --git a/clang/test/BoundsSafety/CodeGen/addrof-member-to-single-O2.c b/clang/test/BoundsSafety/CodeGen/addrof-member-to-single-O2.c index b1a637bed382e..367906f28bff3 100644 --- a/clang/test/BoundsSafety/CodeGen/addrof-member-to-single-O2.c +++ b/clang/test/BoundsSafety/CodeGen/addrof-member-to-single-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple arm64e-apple-iphoneos %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64e-apple-iphoneos %s -o - | FileCheck %s @@ -13,7 +12,14 @@ struct foo { // CHECK-LABEL: @addrof_single_ptr_to_single( // CHECK-NEXT: entry: -// CHECK-NEXT: ret ptr [[F:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[F:%.*]], i64 8 +// CHECK-NEXT: [[DOTNOT4:%.*]] = icmp ugt ptr [[F]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT4]], label [[TRAP:%.*]], label [[CONT2:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: ret ptr [[F]] // char **addrof_single_ptr_to_single(struct foo *f) { return &f->ptr; @@ -22,6 +28,13 @@ char **addrof_single_ptr_to_single(struct foo *f) { // CHECK-LABEL: @addrof_single_i_to_single( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F:%.*]], i64 8 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[F]], i64 12 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT2:%.*]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: // CHECK-NEXT: ret ptr [[TMP0]] // int *addrof_single_i_to_single(struct foo *f) { @@ -31,6 +44,13 @@ int *addrof_single_i_to_single(struct foo *f) { // CHECK-LABEL: @addrof_single_l_to_single( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F:%.*]], i64 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[F]], i64 24 +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT2:%.*]], !prof [[PROF6]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: // CHECK-NEXT: ret ptr [[TMP0]] // long *addrof_single_l_to_single(struct foo *f) { @@ -42,7 +62,7 @@ static inline char **__addrof_bidi_ptr_to_single(struct foo *__bidi_indexable f) } // CHECK-LABEL: @addrof_bidi_ptr_to_single( -// CHECK-NEXT: __addrof_bidi_ptr_to_single.exit: +// CHECK-NEXT: entry: // CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 // CHECK-NEXT: ret ptr [[F]] // @@ -52,8 +72,8 @@ char **addrof_bidi_ptr_to_single(void) { } // CHECK-LABEL: @addrof_bidi_ptr_to_single_oob_upper( -// CHECK-NEXT: trap.i: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // char **addrof_bidi_ptr_to_single_oob_upper(void) { @@ -65,20 +85,8 @@ char **addrof_bidi_ptr_to_single_oob_upper(void) { // CHECK-LABEL: @addrof_bidi_ptr_to_single_oob_lower( // CHECK-NEXT: entry: -// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_PTR_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap.i: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: __addrof_bidi_ptr_to_single.exit: -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] -// CHECK-NEXT: ret ptr [[BOUND_PTR_ARITH]] // char **addrof_bidi_ptr_to_single_oob_lower(void) { struct foo f; @@ -91,9 +99,9 @@ static inline int *__addrof_bidi_i_to_single(struct foo *__bidi_indexable f) { } // CHECK-LABEL: @addrof_bidi_i_to_single( -// CHECK-NEXT: __addrof_bidi_i_to_single.exit: +// CHECK-NEXT: cont3.i: // CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6:[0-9]+]] // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 8 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] // CHECK-NEXT: ret ptr [[TMP0]] @@ -104,7 +112,7 @@ int *addrof_bidi_i_to_single(void) { } // CHECK-LABEL: @addrof_bidi_i_to_single_oob_upper( -// CHECK-NEXT: trap.i: +// CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // @@ -116,21 +124,8 @@ int *addrof_bidi_i_to_single_oob_upper(void) { // CHECK-LABEL: @addrof_bidi_i_to_single_oob_lower( // CHECK-NEXT: entry: -// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_I_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap.i: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: __addrof_bidi_i_to_single.exit: -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[F]], i64 -16 -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] -// CHECK-NEXT: ret ptr [[TMP3]] // int *addrof_bidi_i_to_single_oob_lower(void) { struct foo f; @@ -156,7 +151,7 @@ long *addrof_bidi_l_to_single(void) { } // CHECK-LABEL: @addrof_bidi_l_to_single_oob_upper( -// CHECK-NEXT: trap.i: +// CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // @@ -168,21 +163,8 @@ long *addrof_bidi_l_to_single_oob_upper(void) { // CHECK-LABEL: @addrof_bidi_l_to_single_oob_lower( // CHECK-NEXT: entry: -// CHECK-NEXT: [[F:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[F]], i64 24 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[F]], i64 -24 -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[F]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[__ADDROF_BIDI_L_TO_SINGLE_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap.i: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: __addrof_bidi_l_to_single.exit: -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[F]], i64 -8 -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[F]]) #[[ATTR6]] -// CHECK-NEXT: ret ptr [[TMP3]] // long *addrof_bidi_l_to_single_oob_lower(void) { struct foo f; diff --git a/clang/test/BoundsSafety/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c b/clang/test/BoundsSafety/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c index dab393a36813e..c066199f78765 100644 --- a/clang/test/BoundsSafety/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c +++ b/clang/test/BoundsSafety/CodeGen/alloc-sized-calloc/alloc-sized-calloc.c @@ -1,6 +1,5 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -emit-llvm -triple arm64e -fbounds-safety %s -o - | FileCheck %s // RUN: %clang_cc1 -emit-llvm -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental %s -o - | FileCheck %s @@ -9,8 +8,9 @@ #include "mock-header.h" -// CHECK-LABEL: @foo( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local i32 @foo( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[CNT:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[SIZ:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -23,8 +23,8 @@ // CHECK-NEXT: [[CALL:%.*]] = call ptr @my_calloc(i32 noundef [[TMP0]], i32 noundef [[TMP1]]) #[[ATTR4:[0-9]+]] // CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP0]], [[TMP1]] // CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[CALL]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: +// CHECK-NEXT: br i1 [[TMP2]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[BOUNDSCHECK_NULL:.*]], {{!annotation ![0-9]+}} +// CHECK: [[BOUNDSCHECK_NOTNULL]]: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[MUL]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[IDX_EXT]] // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 @@ -33,16 +33,16 @@ // CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[CALL]], ptr [[TMP5]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] -// CHECK: boundscheck.null: +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] -// CHECK: boundscheck.cont: +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 @@ -61,25 +61,32 @@ // CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[CNT]], align 4 // CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP12]], 1 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[SUB]] to i64 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[TMP13]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont: -// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[TMP13]], [[WIDE_PTR_LB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT9:%.*]], label [[TRAP8:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap8: +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT9:.*]], label %[[TRAP8:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP8]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT9]]: +// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label %[[CONT11:.*]], label %[[TRAP10:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP10]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont9: -// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK-NEXT: ret i32 [[TMP16]] +// CHECK: [[CONT11]]: +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP17]] // int foo() { int cnt = 10; @@ -87,3 +94,6 @@ int foo() { int *ptr = my_calloc(cnt, siz); return ptr[cnt-1]; } +//. +// CHECK: [[PROF4]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/array-bound-deref-addrof.c b/clang/test/BoundsSafety/CodeGen/array-bound-deref-addrof.c index 2197b5247eb69..a9dd42214886b 100644 --- a/clang/test/BoundsSafety/CodeGen/array-bound-deref-addrof.c +++ b/clang/test/BoundsSafety/CodeGen/array-bound-deref-addrof.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 @@ -8,71 +7,85 @@ #include // CHECK-O0-LABEL: @foo( -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 -// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-O0: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 -// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARR]], ptr [[TMP1]], align 8 -// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: store ptr [[TMP0]], ptr [[TMP2]], align 8 -// CHECK-O0: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARR]], ptr [[TMP3]], align 8 -// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 -// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 -// CHECK-O0: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP6]], align 8 -// CHECK-O0: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK-O0: store ptr [[UPPER]], ptr [[TMP7]], align 8 -// CHECK-O0: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 -// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK-O0: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-O0: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 10 -// CHECK-O0: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-O0: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0: ret i32 [[TMP12]] +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARR]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARR]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr [10 x i32], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP10]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap12: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont13: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap14: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont15: +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap16: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont17: +// CHECK-O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP15]] // // CHECK-O2-LABEL: @foo( -// CHECK-O2: {{.*}}: -// CHECK-O2: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2: unreachable +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int foo() { int arr[10]; @@ -81,70 +94,84 @@ int foo() { } // CHECK-O0-LABEL: @bar( -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 -// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-O0: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 -// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARR]], ptr [[TMP1]], align 8 -// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: store ptr [[TMP0]], ptr [[TMP2]], align 8 -// CHECK-O0: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARR]], ptr [[TMP3]], align 8 -// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 -// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 -// CHECK-O0: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP6]], align 8 -// CHECK-O0: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK-O0: store ptr [[UPPER]], ptr [[TMP7]], align 8 -// CHECK-O0: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 -// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK-O0: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-O0: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 9 -// CHECK-O0: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-O0: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0: ret i32 [[TMP12]] +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr [10 x i32], ptr [[ARR]], i64 1 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARR]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARR]], ptr [[TMP3]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr [10 x i32], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[WIDE_PTR_PTR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP8]], align 8 +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP9]], align 8 +// CHECK-O0-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP10]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap12: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont13: +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap14: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont15: +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap16: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont17: +// CHECK-O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP15]] // // CHECK-O2-LABEL: @bar( -// CHECK-O2: {{.*}}: -// CHECK-O2: ret i32 undef +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 undef // int bar() { int arr[10]; diff --git a/clang/test/BoundsSafety/CodeGen/array-decay.c b/clang/test/BoundsSafety/CodeGen/array-decay.c index e397937981a0f..9c0f50f3229f6 100644 --- a/clang/test/BoundsSafety/CodeGen/array-decay.c +++ b/clang/test/BoundsSafety/CodeGen/array-decay.c @@ -1,51 +1,57 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // CHECK-O0-LABEL: @foo( -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 -// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) -// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 -// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 -// CHECK-O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK-O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 -// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK-O0: ret i32 [[TMP6]] +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP7]] // // CHECK-O2-LABEL: @foo( -// CHECK-O2: {{.*}}: -// CHECK-O2: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2: unreachable +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int foo() { int arr[10] = {0}; @@ -54,45 +60,52 @@ int foo() { } // CHECK-O0-LABEL: @bar( -// CHECK-O0: {{.*}}: -// CHECK-O0: [[ARR:%.*]] = alloca [10 x i32], align 4 -// CHECK-O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) -// CHECK-O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 -// CHECK-O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 -// CHECK-O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK-O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK-O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK-O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 -// CHECK-O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: {{.*}}: -// CHECK-O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0: unreachable -// CHECK-O0: {{.*}}: -// CHECK-O0: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK-O0: ret i32 [[TMP6]] +// CHECK-O0-NEXT: entry: +// CHECK-O0-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 +// CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ARR]], i8 0, i64 40, i1 false) +// CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 +// CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK-O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK-O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont: +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap1: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont2: +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP7]] // // CHECK-O2-LABEL: @bar( -// CHECK-O2: entry: -// CHECK-O2: ret i32 0 +// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: ret i32 0 // int bar() { int arr[10] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/const-bound-ptr-conversion.c b/clang/test/BoundsSafety/CodeGen/const-bound-ptr-conversion.c index 3e94635f98fc3..c4635395086cd 100644 --- a/clang/test/BoundsSafety/CodeGen/const-bound-ptr-conversion.c +++ b/clang/test/BoundsSafety/CodeGen/const-bound-ptr-conversion.c @@ -1,51 +1,57 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O0 // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O2 // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O0 // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK_O2 // CHECK_O0-LABEL: @foo( -// CHECK_O0: {{.*}}: -// CHECK_O0: [[ARRAY:%.*]] = alloca [10 x i32], align 16 -// CHECK_O0: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK_O0: [[LOCAL:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK_O0: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK_O0: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 40, i1 false) -// CHECK_O0: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARRAY]], i64 0, i64 0 -// CHECK_O0: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 -// CHECK_O0: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 -// CHECK_O0: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK_O0: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 -// CHECK_O0: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK_O0: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 -// CHECK_O0: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK_O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LOCAL]], ptr align 8 [[PTR]], i64 24, i1 false) -// CHECK_O0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[LOCAL]], i64 24, i1 false) -// CHECK_O0: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK_O0: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK_O0: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK_O0: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK_O0: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK_O0: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK_O0: [[TMP3:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK_O0: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: entry: +// CHECK_O0-NEXT: [[ARRAY:%.*]] = alloca [10 x i32], align 16 +// CHECK_O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK_O0-NEXT: [[LOCAL:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK_O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK_O0-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 40, i1 false) +// CHECK_O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARRAY]], i64 0, i64 0 +// CHECK_O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 +// CHECK_O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 +// CHECK_O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 +// CHECK_O0-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 1 +// CHECK_O0-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 +// CHECK_O0-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 2 +// CHECK_O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 +// CHECK_O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LOCAL]], ptr align 8 [[PTR]], i64 24, i1 false) +// CHECK_O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[LOCAL]], i64 24, i1 false) +// CHECK_O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK_O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 +// CHECK_O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK_O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 +// CHECK_O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK_O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK_O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK_O0: trap: -// CHECK_O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK_O0: unreachable +// CHECK_O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK_O0: cont: -// CHECK_O0: [[TMP4:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK_O0: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK_O0: trap1: -// CHECK_O0: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK_O0: unreachable +// CHECK_O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK_O0: cont2: -// CHECK_O0: [[TMP5:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK_O0: ret i32 [[TMP5]] +// CHECK_O0-NEXT: [[TMP6:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK_O0: trap3: +// CHECK_O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK_O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK_O0: cont4: +// CHECK_O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK_O0-NEXT: ret i32 [[TMP7]] // // CHECK_O2-LABEL: @foo( -// CHECK_O2: {{.*}}: -// CHECK_O2: ret i32 0 +// CHECK_O2-NEXT: entry: +// CHECK_O2-NEXT: ret i32 0 // int foo(void) { int array[10] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/constant-eval-count-static-init.c b/clang/test/BoundsSafety/CodeGen/constant-eval-count-static-init.c index 44ba3b6fde46f..84acda61f90a0 100644 --- a/clang/test/BoundsSafety/CodeGen/constant-eval-count-static-init.c +++ b/clang/test/BoundsSafety/CodeGen/constant-eval-count-static-init.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s #include @@ -34,25 +33,32 @@ const Item oidRsa = { _oidRsa, sizeof(_oidRsa)}; // CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP4]], align 8 // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 3 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 3 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[TMP5]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[TMP5]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT3:%.*]], label [[TRAP2:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap2: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont3: -// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP5]], align 4 -// CHECK-NEXT: ret i32 [[TMP8]] +// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap4: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont5: +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP9]] // int main() { return oidRsa.data[3]; // trap diff --git a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c index 551dc10a9760d..28de7e41c41e0 100644 --- a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c +++ b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob1-O2.c @@ -11,8 +11,8 @@ struct S { int l; }; -// CHECK-O2-LABEL: define dso_local noundef i32 @foo -// CHECK-O2-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-O2-LABEL: define dso_local noundef i32 @foo( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2:![0-9]+]] // CHECK-O2-NEXT: unreachable, !annotation [[META2]] @@ -27,8 +27,8 @@ int foo () { return s.bp2[9]; // trap : oob s.bp2[9] } -// CHECK-O2-LABEL: define dso_local i32 @bar -// CHECK-O2-SAME: () local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-O2-LABEL: define dso_local i32 @bar( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] { // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: ret i32 undef // @@ -41,6 +41,3 @@ int bar () { return s.bp2[8]; // ok } -//. -// CHECK-O2: [[META2]] = !{!"bounds-safety-generic", !"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} -//. diff --git a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c index 39a10e41bf936..df26a4e6bbb61 100644 --- a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c +++ b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/count-attr-fields-assign-2-oob2.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 @@ -28,10 +27,10 @@ struct S { // CHECK-O0-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK-O0-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[AGG_TEMP43:%.*]] = alloca [[STRUCT_S]], align 8 -// CHECK-O0-NEXT: [[AGG_TEMP56:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0-NEXT: [[AGG_TEMP57:%.*]] = alloca [[STRUCT_S]], align 8 -// CHECK-O0-NEXT: [[AGG_TEMP73:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-O0-NEXT: [[AGG_TEMP74:%.*]] = alloca [[STRUCT_S]], align 8 +// CHECK-O0-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP59:%.*]] = alloca [[STRUCT_S]], align 8 +// CHECK-O0-NEXT: [[AGG_TEMP77:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP78:%.*]] = alloca [[STRUCT_S]], align 8 // CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 // CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 @@ -48,12 +47,12 @@ struct S { // CHECK-O0-NEXT: store ptr [[UPPER3]], ptr [[TMP4]], align 8 // CHECK-O0-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 // CHECK-O0-NEXT: store ptr [[ARRAYDECAY2]], ptr [[TMP5]], align 8 -// CHECK-O0-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: br i1 true, label [[CONT5:%.*]], label [[TRAP4:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 true, label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap4: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -109,12 +108,12 @@ struct S { // CHECK-O0-NEXT: store ptr [[UPPER19]], ptr [[TMP20]], align 8 // CHECK-O0-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 // CHECK-O0-NEXT: store ptr [[ARRAYDECAY18]], ptr [[TMP21]], align 8 -// CHECK-O0-NEXT: br i1 true, label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 true, label [[CONT21:%.*]], label [[TRAP20:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap20: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont21: -// CHECK-O0-NEXT: br i1 true, label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 true, label [[CONT23:%.*]], label [[TRAP22:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap22: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -171,98 +170,119 @@ struct S { // CHECK-O0-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 -// CHECK-O0-NEXT: [[TMP31:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP31]], label [[CONT53:%.*]], label [[TRAP52:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP31:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP32:%.*]] = icmp ule ptr [[TMP31]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP32]], label [[CONT53:%.*]], label [[TRAP52:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap52: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont53: -// CHECK-O0-NEXT: [[TMP32:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP32]], label [[CONT55:%.*]], label [[TRAP54:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP33:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP31]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP33]], label [[CONT55:%.*]], label [[TRAP54:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap54: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont55: +// CHECK-O0-NEXT: [[TMP34:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP34]], label [[CONT57:%.*]], label [[TRAP56:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap56: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont57: // CHECK-O0-NEXT: store i32 [[TMP24]], ptr [[ARRAYIDX]], align 4 // CHECK-O0-NEXT: br label [[FOR_INC:%.*]] // CHECK-O0: for.inc: -// CHECK-O0-NEXT: [[TMP33:%.*]] = load i32, ptr [[I]], align 4 -// CHECK-O0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP33]], 1 +// CHECK-O0-NEXT: [[TMP35:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-O0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP35]], 1 // CHECK-O0-NEXT: store i32 [[INC]], ptr [[I]], align 4 -// CHECK-O0-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]] +// CHECK-O0-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP6:![0-9]+]] // CHECK-O0: for.end: -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[S]], i64 24, i1 false) -// CHECK-O0-NEXT: [[L58:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP57]], i32 0, i32 2 -// CHECK-O0-NEXT: [[TMP34:%.*]] = load i32, ptr [[L58]], align 8 -// CHECK-O0-NEXT: [[BP259:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP57]], i32 0, i32 1 -// CHECK-O0-NEXT: [[TMP35:%.*]] = load ptr, ptr [[BP259]], align 8 -// CHECK-O0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP34]], 1 -// CHECK-O0-NEXT: [[IDX_EXT60:%.*]] = sext i32 [[ADD]] to i64 -// CHECK-O0-NEXT: [[ADD_PTR61:%.*]] = getelementptr inbounds i32, ptr [[TMP35]], i64 [[IDX_EXT60]] -// CHECK-O0-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 0 -// CHECK-O0-NEXT: store ptr [[TMP35]], ptr [[TMP36]], align 8 -// CHECK-O0-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 1 -// CHECK-O0-NEXT: store ptr [[ADD_PTR61]], ptr [[TMP37]], align 8 -// CHECK-O0-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 2 -// CHECK-O0-NEXT: store ptr [[TMP35]], ptr [[TMP38]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 0 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR63:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR62]], align 8 -// CHECK-O0-NEXT: [[ARRAYIDX64:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR63]], i64 8 -// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 1 -// CHECK-O0-NEXT: [[WIDE_PTR_UB66:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR65]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP56]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8 -// CHECK-O0-NEXT: [[TMP39:%.*]] = icmp ult ptr [[ARRAYIDX64]], [[WIDE_PTR_UB66]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP39]], label [[CONT70:%.*]], label [[TRAP69:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: trap69: -// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-O0: cont70: -// CHECK-O0-NEXT: [[TMP40:%.*]] = icmp uge ptr [[ARRAYIDX64]], [[WIDE_PTR_LB68]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP40]], label [[CONT72:%.*]], label [[TRAP71:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP59]], ptr align 8 [[S]], i64 24, i1 false) +// CHECK-O0-NEXT: [[L60:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP59]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP36:%.*]] = load i32, ptr [[L60]], align 8 +// CHECK-O0-NEXT: [[BP261:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP59]], i32 0, i32 1 +// CHECK-O0-NEXT: [[TMP37:%.*]] = load ptr, ptr [[BP261]], align 8 +// CHECK-O0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP36]], 1 +// CHECK-O0-NEXT: [[IDX_EXT62:%.*]] = sext i32 [[ADD]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR63:%.*]] = getelementptr inbounds i32, ptr [[TMP37]], i64 [[IDX_EXT62]] +// CHECK-O0-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP37]], ptr [[TMP38]], align 8 +// CHECK-O0-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR63]], ptr [[TMP39]], align 8 +// CHECK-O0-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP37]], ptr [[TMP40]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR64:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR65:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR64]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX66:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR65]], i64 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB68:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR67]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB70:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR69]], align 8 +// CHECK-O0-NEXT: [[TMP41:%.*]] = getelementptr i32, ptr [[ARRAYIDX66]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP42:%.*]] = icmp ule ptr [[TMP41]], [[WIDE_PTR_UB68]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP42]], label [[CONT72:%.*]], label [[TRAP71:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} // CHECK-O0: trap71: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont72: -// CHECK-O0-NEXT: [[TMP41:%.*]] = load i32, ptr [[ARRAYIDX64]], align 4 -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP74]], ptr align 8 [[S]], i64 24, i1 false) -// CHECK-O0-NEXT: [[L75:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP74]], i32 0, i32 2 -// CHECK-O0-NEXT: [[TMP42:%.*]] = load i32, ptr [[L75]], align 8 -// CHECK-O0-NEXT: [[BP76:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP74]], i32 0, i32 0 -// CHECK-O0-NEXT: [[TMP43:%.*]] = load ptr, ptr [[BP76]], align 8 -// CHECK-O0-NEXT: [[IDX_EXT77:%.*]] = sext i32 [[TMP42]] to i64 -// CHECK-O0-NEXT: [[ADD_PTR78:%.*]] = getelementptr inbounds i32, ptr [[TMP43]], i64 [[IDX_EXT77]] -// CHECK-O0-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 0 -// CHECK-O0-NEXT: store ptr [[TMP43]], ptr [[TMP44]], align 8 -// CHECK-O0-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 1 -// CHECK-O0-NEXT: store ptr [[ADD_PTR78]], ptr [[TMP45]], align 8 -// CHECK-O0-NEXT: [[TMP46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 2 -// CHECK-O0-NEXT: store ptr [[TMP43]], ptr [[TMP46]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR79:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 0 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR80:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR79]], align 8 -// CHECK-O0-NEXT: [[ARRAYIDX81:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR80]], i64 8 -// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 1 -// CHECK-O0-NEXT: [[WIDE_PTR_UB83:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR82]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB85:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR84]], align 8 -// CHECK-O0-NEXT: [[TMP47:%.*]] = icmp ult ptr [[ARRAYIDX81]], [[WIDE_PTR_UB83]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP47]], label [[CONT87:%.*]], label [[TRAP86:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: trap86: +// CHECK-O0-NEXT: [[TMP43:%.*]] = icmp ule ptr [[ARRAYIDX66]], [[TMP41]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP43]], label [[CONT74:%.*]], label [[TRAP73:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap73: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont74: +// CHECK-O0-NEXT: [[TMP44:%.*]] = icmp uge ptr [[ARRAYIDX66]], [[WIDE_PTR_LB70]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP44]], label [[CONT76:%.*]], label [[TRAP75:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap75: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont76: +// CHECK-O0-NEXT: [[TMP45:%.*]] = load i32, ptr [[ARRAYIDX66]], align 4 +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP78]], ptr align 8 [[S]], i64 24, i1 false) +// CHECK-O0-NEXT: [[L79:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP78]], i32 0, i32 2 +// CHECK-O0-NEXT: [[TMP46:%.*]] = load i32, ptr [[L79]], align 8 +// CHECK-O0-NEXT: [[BP80:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[AGG_TEMP78]], i32 0, i32 0 +// CHECK-O0-NEXT: [[TMP47:%.*]] = load ptr, ptr [[BP80]], align 8 +// CHECK-O0-NEXT: [[IDX_EXT81:%.*]] = sext i32 [[TMP46]] to i64 +// CHECK-O0-NEXT: [[ADD_PTR82:%.*]] = getelementptr inbounds i32, ptr [[TMP47]], i64 [[IDX_EXT81]] +// CHECK-O0-NEXT: [[TMP48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 0 +// CHECK-O0-NEXT: store ptr [[TMP47]], ptr [[TMP48]], align 8 +// CHECK-O0-NEXT: [[TMP49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 1 +// CHECK-O0-NEXT: store ptr [[ADD_PTR82]], ptr [[TMP49]], align 8 +// CHECK-O0-NEXT: [[TMP50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 2 +// CHECK-O0-NEXT: store ptr [[TMP47]], ptr [[TMP50]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR84:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR83]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX85:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR84]], i64 8 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR86:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB87:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR86]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR88:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP77]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB89:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR88]], align 8 +// CHECK-O0-NEXT: [[TMP51:%.*]] = getelementptr i32, ptr [[ARRAYIDX85]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP52:%.*]] = icmp ule ptr [[TMP51]], [[WIDE_PTR_UB87]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP52]], label [[CONT91:%.*]], label [[TRAP90:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap90: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont91: +// CHECK-O0-NEXT: [[TMP53:%.*]] = icmp ule ptr [[ARRAYIDX85]], [[TMP51]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP53]], label [[CONT93:%.*]], label [[TRAP92:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap92: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-O0: cont87: -// CHECK-O0-NEXT: [[TMP48:%.*]] = icmp uge ptr [[ARRAYIDX81]], [[WIDE_PTR_LB85]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP48]], label [[CONT89:%.*]], label [[TRAP88:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: trap88: +// CHECK-O0: cont93: +// CHECK-O0-NEXT: [[TMP54:%.*]] = icmp uge ptr [[ARRAYIDX85]], [[WIDE_PTR_LB89]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP54]], label [[CONT95:%.*]], label [[TRAP94:%.*]], !prof [[PROF2]], {{!annotation ![0-9]+}} +// CHECK-O0: trap94: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-O0: cont89: -// CHECK-O0-NEXT: [[TMP49:%.*]] = load i32, ptr [[ARRAYIDX81]], align 4 -// CHECK-O0-NEXT: [[ADD90:%.*]] = add nsw i32 [[TMP41]], [[TMP49]] -// CHECK-O0-NEXT: ret i32 [[ADD90]] +// CHECK-O0: cont95: +// CHECK-O0-NEXT: [[TMP55:%.*]] = load i32, ptr [[ARRAYIDX85]], align 4 +// CHECK-O0-NEXT: [[ADD96:%.*]] = add nsw i32 [[TMP45]], [[TMP55]] +// CHECK-O0-NEXT: ret i32 [[ADD96]] // // CHECK-O2-LABEL: @foo( -// CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: trap: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // diff --git a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c index 92f7309f51c0c..f35cc3fda7897 100644 --- a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c +++ b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/dep-count-init-list-basic-O2.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple x86_64 %s -o - | FileCheck %s #include @@ -11,7 +10,7 @@ struct S { // CHECK-LABEL: @TestInitFail1( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestInitFail1() { @@ -22,7 +21,7 @@ void TestInitFail1() { // CHECK-LABEL: @TestInitFail2( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestInitFail2() { @@ -39,7 +38,7 @@ struct SU { // CHECK-LABEL: @TestUInitFail( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestUInitFail() { @@ -83,7 +82,7 @@ void TestAccessOK() { // CHECK-LABEL: @TestAccessFail( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestAccessFail() { @@ -95,20 +94,8 @@ void TestAccessFail() { // CHECK-LABEL: @TestAccessFail2( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ARR:%.*]] = alloca [9 x i32], align 16 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 36, ptr nonnull [[ARR]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 36 -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 -4 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT47:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont47: -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 36, ptr nonnull [[ARR]]) #[[ATTR6]] -// CHECK-NEXT: ret void // void TestAccessFail2() { int arr[9] = {0}; @@ -119,7 +106,7 @@ void TestAccessFail2() { // CHECK-LABEL: @TestAccessFail3( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestAccessFail3() { diff --git a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/index-extension.c b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/index-extension.c index 01c1a5d818fcd..c7ed6fd7cab68 100644 --- a/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/index-extension.c +++ b/clang/test/BoundsSafety/CodeGen/count-dependent-assignment-checks/index-extension.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK #include @@ -10,16 +9,19 @@ // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = sext i8 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_char(int *__counted_by(n) dst, unsigned n, char idx) { @@ -32,16 +34,19 @@ void idx_char(int *__counted_by(n) dst, unsigned n, char idx) { // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_unsigned_char(int *__counted_by(n) dst, unsigned n, unsigned char idx) { @@ -54,16 +59,19 @@ void idx_unsigned_char(int *__counted_by(n) dst, unsigned n, unsigned char idx) // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = sext i16 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_short_int(int *__counted_by(n) dst, unsigned n, short int idx) { @@ -76,16 +84,19 @@ void idx_short_int(int *__counted_by(n) dst, unsigned n, short int idx) { // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = zext i16 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_short_unsigned(int *__counted_by(n) dst, unsigned n, short unsigned idx) { @@ -98,16 +109,19 @@ void idx_short_unsigned(int *__counted_by(n) dst, unsigned n, short unsigned idx // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_int(int *__counted_by(n) dst, unsigned n, int idx) { @@ -120,16 +134,19 @@ void idx_int(int *__counted_by(n) dst, unsigned n, int idx) { // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IDX:%.*]] to i64 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_unsigned(int *__counted_by(n) dst, unsigned n, unsigned idx) { @@ -141,16 +158,19 @@ void idx_unsigned(int *__counted_by(n) dst, unsigned n, unsigned idx) { // CHECK-NEXT: entry: // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_long_int(int *__counted_by(n) dst, unsigned n, long int idx) { @@ -162,16 +182,19 @@ void idx_long_int(int *__counted_by(n) dst, unsigned n, long int idx) { // CHECK-NEXT: entry: // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_long_unsigned(int *__counted_by(n) dst, unsigned n, long unsigned idx) { @@ -183,16 +206,19 @@ void idx_long_unsigned(int *__counted_by(n) dst, unsigned n, long unsigned idx) // CHECK-NEXT: entry: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[N:%.*]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IDX:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[DST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont1: -// CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // void idx_long_unsigned_counted_by_int(int *__counted_by(n) dst, int n, long unsigned idx) { diff --git a/clang/test/BoundsSafety/CodeGen/count-return.c b/clang/test/BoundsSafety/CodeGen/count-return.c index cc204b05da867..c8684577791f4 100644 --- a/clang/test/BoundsSafety/CodeGen/count-return.c +++ b/clang/test/BoundsSafety/CodeGen/count-return.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 @@ -37,33 +36,49 @@ int *__sized_by(len) alloc(int len); // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BUFBOUND]], i64 24, i1 false) // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ult ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp uge ptr [[TMP7]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont4: -// CHECK-O0-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP10]] +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap5: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont6: +// CHECK-O0-NEXT: [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP11]] // // CHECK-O2-LABEL: @Test1( -// CHECK-O2-NEXT: cont3: +// CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: [[CALL:%.*]] = tail call ptr @alloc(i32 noundef 16) #[[ATTR4:[0-9]+]] // CHECK-O2-NEXT: [[CALL1:%.*]] = tail call ptr @alloc(i32 noundef 40) #[[ATTR4]] -// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL1]], i64 36 -// CHECK-O2-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} -// CHECK-O2-NEXT: ret i32 [[TMP1]] +// CHECK-O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[CALL1]], i64 36 +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL1]], i64 40, {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[TMP1:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[CALL1]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: [[OR_COND5:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: br i1 [[OR_COND5]], label [[CONT4:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2: trap: +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O2: cont4: +// CHECK-O2-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} +// CHECK-O2-NEXT: ret i32 [[TMP3]] // int Test1() { int len = 16; @@ -100,31 +115,38 @@ int Test1() { // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[BUFBOUND]], i64 24, i1 false) // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ult ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp uge ptr [[TMP7]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont4: -// CHECK-O0-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP10]] +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap5: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont6: +// CHECK-O0-NEXT: [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP11]] // // CHECK-O2-LABEL: @Test2( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: [[CALL:%.*]] = tail call ptr @alloc(i32 noundef 16) #[[ATTR4]] // CHECK-O2-NEXT: [[CALL1:%.*]] = tail call ptr @alloc(i32 noundef 40) #[[ATTR4]] -// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int Test2() { diff --git a/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O0.c b/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O0.c index db14a37c3e32e..97aeaea61d469 100644 --- a/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O0.c +++ b/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O0.c @@ -1,34 +1,110 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 - // RUN: %clang_cc1 -fbounds-safety -Wno-bounds-safety-init-list -O0 -triple arm64 -emit-llvm %s -o - | FileCheck %s #include // TODO: rdar://114446928 -// CHECK-LABEL: define dso_local ptr @foo -// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-LABEL: define dso_local ptr @foo( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP15:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP25:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP38:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB3]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END37:%.*]], !annotation [[META2]] +// CHECK: land.lhs.true: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP14:%.*]] = icmp ule ptr [[WIDE_PTR_LB6]], [[WIDE_PTR_PTR9]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP14]], label [[LAND_RHS:%.*]], label [[LAND_END37]], !annotation [[META2]] +// CHECK: land.rhs: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP15]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR17:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR16]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB19:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR18]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB21:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR20]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR17]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK: lor.rhs: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP25]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR27:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR26]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB29:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR28]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP25]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB24]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR27]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] +// CHECK-NEXT: [[CMP32:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP32]], label [[LAND_RHS34:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK: land.rhs34: +// CHECK-NEXT: [[CMP35:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK: land.end: +// CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP35]], [[LAND_RHS34]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK: lor.end: +// CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP1]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END37]], !annotation [[META2]] +// CHECK: land.end37: +// CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP2]], [[LOR_END]] ], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP38]], ptr align 8 [[P]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR40]] // int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { return p; } -// CHECK-LABEL: define dso_local void @foo_assign -// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @foo_assign( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 @@ -48,7 +124,7 @@ int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { // CHECK-NEXT: store i32 [[TMP0]], ptr [[SIZE]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE]], align 4 // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false), !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] @@ -111,9 +187,9 @@ int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { // CHECK-NEXT: br label [[LAND_END39]], !annotation [[META2]] // CHECK: land.end39: // CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP3]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[P]], i64 24, i1 false) @@ -131,8 +207,8 @@ void foo_assign(int * __bidi_indexable p, int len) { int * __counted_by_or_null(size) p2 = p; } -// CHECK-LABEL: define dso_local void @bar -// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @bar( +// CHECK-SAME: ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 @@ -140,8 +216,8 @@ void foo_assign(int * __bidi_indexable p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] @@ -167,8 +243,8 @@ int * __bidi_indexable bar(int * __counted_by_or_null(len) p, int len) { return p; } -// CHECK-LABEL: define dso_local void @bar_assign -// CHECK-SAME: (ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @bar_assign( +// CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 @@ -177,8 +253,8 @@ int * __bidi_indexable bar(int * __counted_by_or_null(len) p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] @@ -204,8 +280,8 @@ void bar_assign(int * __counted_by_or_null(len) p, int len) { int * __bidi_indexable p2 = p; } -// CHECK-LABEL: define dso_local void @ptr_oob -// CHECK-SAME: () #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @ptr_oob( +// CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -302,7 +378,7 @@ void bar_assign(int * __counted_by_or_null(len) p, int len) { // CHECK-NEXT: br label [[LAND_END34]], !annotation [[META2]] // CHECK: land.end34: // CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP14]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] @@ -324,8 +400,8 @@ void ptr_oob(void) { int *__counted_by_or_null(4) q = p; } -// CHECK-LABEL: define dso_local void @null_count_neg -// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @null_count_neg( +// CHECK-SAME: ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 @@ -340,8 +416,8 @@ void ptr_oob(void) { // CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P]], i8 0, i64 24, i1 false) -// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] -// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META4]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META5:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META5]] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] @@ -405,7 +481,7 @@ void ptr_oob(void) { // CHECK-NEXT: br label [[LAND_END35]], !annotation [[META2]] // CHECK: land.end35: // CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP1]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] @@ -421,8 +497,8 @@ void ptr_oob(void) { // CHECK-NEXT: store ptr [[WIDE_PTR_PTR38]], ptr [[Q]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[Q]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP4]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 [[IDX_EXT]] @@ -453,8 +529,8 @@ int *__bidi_indexable null_count_neg(void) { return q; } -// CHECK-LABEL: define dso_local void @null_count_too_big -// CHECK-SAME: (ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// CHECK-LABEL: define dso_local void @null_count_too_big( +// CHECK-SAME: ptr dead_on_unwind noalias writable sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 @@ -469,8 +545,8 @@ int *__bidi_indexable null_count_neg(void) { // CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P]], i8 0, i64 24, i1 false) -// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4]] -// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META4]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META5]] +// CHECK-NEXT: store ptr null, ptr [[Q]], align 8, !annotation [[META5]] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] @@ -534,7 +610,7 @@ int *__bidi_indexable null_count_neg(void) { // CHECK-NEXT: br label [[LAND_END35]], !annotation [[META2]] // CHECK: land.end35: // CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP1]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] @@ -550,8 +626,8 @@ int *__bidi_indexable null_count_neg(void) { // CHECK-NEXT: store ptr [[WIDE_PTR_PTR38]], ptr [[Q]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[Q]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[TMP3]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP4]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 [[IDX_EXT]] @@ -582,8 +658,3 @@ int *__bidi_indexable null_count_too_big(void) { return q; } -//. -// CHECK: [[META2]] = !{!"bounds-safety-generic"} -// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} -// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} -//. diff --git a/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O2.c b/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O2.c index f9825f548bac9..4a442484b1bdd 100644 --- a/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O2.c +++ b/clang/test/BoundsSafety/CodeGen/counted-by-or-null-from-bidi-O2.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 - // RUN: %clang_cc1 -fbounds-safety -Wno-bounds-safety-init-list -O2 -triple arm64 -emit-llvm %s -o - | FileCheck %s #include @@ -10,6 +9,32 @@ // CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// CHECK-NEXT: [[AGG_TEMP1_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_2_0_P_SROA_IDX]], align 8 +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_1_0_COPYLOAD]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label %[[TRAP:.*]], label %[[LAND_LHS_TRUE:.*]], !annotation [[META2]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 +// CHECK-NEXT: [[AGG_TEMP4_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_P_SROA_IDX]], align 8, !tbaa [[TBAA3:![0-9]+]] +// CHECK-NEXT: [[CMP14_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP4_SROA_1_0_COPYLOAD]], [[AGG_TEMP_SROA_0_0_COPYLOAD]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[CMP14_NOT]], label %[[TRAP]], label %[[LAND_RHS:.*]], !annotation [[META2]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], null, !annotation [[META2]] +// CHECK-NEXT: br i1 [[TOBOOL_NOT]], label %[[CONT:.*]], label %[[LOR_RHS:.*]], !annotation [[META2]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[LEN]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_1_0_COPYLOAD]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] to i64, !annotation [[META2]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2, !annotation [[META2]] +// CHECK-NEXT: [[CMP32:%.*]] = icmp sge i64 [[SUB_PTR_DIV]], [[CONV]], !annotation [[META2]] +// CHECK-NEXT: [[CMP35:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META2]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP35]], [[CMP32]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label %[[CONT]], label %[[TRAP]], !prof [[PROF10:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT]]: // CHECK-NEXT: ret ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] // int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { @@ -17,17 +42,17 @@ int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { } // CHECK-LABEL: define dso_local void @foo_assign( -// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-SAME: ptr noundef readonly captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[LEN]] to i64 // CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[P]], align 8 // CHECK-NEXT: [[AGG_TEMP_SROA_2_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // CHECK-NEXT: [[AGG_TEMP1_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_2_0_P_SROA_IDX]], align 8 -// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_1_0_COPYLOAD]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_1_0_COPYLOAD]], !annotation [[META2]] // CHECK-NEXT: br i1 [[CMP_NOT]], label %[[TRAP:.*]], label %[[LAND_LHS_TRUE:.*]], !annotation [[META2]] // CHECK: [[LAND_LHS_TRUE]]: // CHECK-NEXT: [[AGG_TEMP_SROA_3_0_P_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 -// CHECK-NEXT: [[AGG_TEMP5_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_P_SROA_IDX]], align 8, !tbaa [[TBAA3:![0-9]+]] +// CHECK-NEXT: [[AGG_TEMP5_SROA_1_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_P_SROA_IDX]], align 8, !tbaa [[TBAA3]] // CHECK-NEXT: [[CMP15_NOT:%.*]] = icmp ugt ptr [[AGG_TEMP5_SROA_1_0_COPYLOAD]], [[AGG_TEMP_SROA_0_0_COPYLOAD]], !annotation [[META2]] // CHECK-NEXT: br i1 [[CMP15_NOT]], label %[[TRAP]], label %[[LAND_RHS:.*]], !annotation [[META2]] // CHECK: [[LAND_RHS]]: @@ -36,14 +61,14 @@ int * __counted_by_or_null(len) foo(int * __bidi_indexable p, int len) { // CHECK: [[LOR_RHS]]: // CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_1_0_COPYLOAD]] to i64, !annotation [[META2]] // CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META8]] // CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2, !annotation [[META2]] // CHECK-NEXT: [[CMP34:%.*]] = icmp sge i64 [[SUB_PTR_DIV]], [[CONV]], !annotation [[META2]] // CHECK-NEXT: [[CMP37:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META2]] // CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP37]], [[CMP34]] -// CHECK-NEXT: br i1 [[SPEC_SELECT]], label %[[CONT]], label %[[TRAP]], !prof [[PROF10:![0-9]+]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label %[[CONT]], label %[[TRAP]], !prof [[PROF10]], !annotation [[META2]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR7:[0-9]+]], !annotation [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // CHECK: [[CONT]]: // CHECK-NEXT: ret void @@ -54,7 +79,7 @@ void foo_assign(int * __bidi_indexable p, int len) { } // CHECK-LABEL: define dso_local void @bar( -// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]], ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[P]], null, !annotation [[META11:![0-9]+]] // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN]] to i64 @@ -72,7 +97,7 @@ int * __bidi_indexable bar(int * __counted_by_or_null(len) p, int len) { } // CHECK-LABEL: define dso_local void @bar_assign( -// CHECK-SAME: ptr noundef readnone captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// CHECK-SAME: ptr noundef readnone captures(none) [[P:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret void // @@ -81,9 +106,9 @@ void bar_assign(int * __counted_by_or_null(len) p, int len) { } // CHECK-LABEL: define dso_local void @ptr_oob( -// CHECK-SAME: ) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// CHECK-SAME: ) local_unnamed_addr #[[ATTR4:[0-9]+]] { // CHECK-NEXT: [[TRAP:.*:]] -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR7]], !annotation [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // void ptr_oob(void) { @@ -94,7 +119,7 @@ void ptr_oob(void) { } // CHECK-LABEL: define dso_local void @null_count_neg( -// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR3]] { +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[AGG_RESULT]], i8 0, i64 24, i1 false) // CHECK-NEXT: ret void @@ -109,7 +134,7 @@ int *__bidi_indexable null_count_neg(void) { } // CHECK-LABEL: define dso_local void @null_count_too_big( -// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR3]] { +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 captures(none) initializes((0, 24)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[AGG_RESULT]], i8 0, i64 24, i1 false) // CHECK-NEXT: ret void diff --git a/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call-O2.c b/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call-O2.c index 1c209d902b89e..9706ffcb85a77 100644 --- a/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call-O2.c +++ b/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 - // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s @@ -164,20 +163,20 @@ void caller_9(int *__counted_by(*len) *out, int *len){ // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA4]] // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[CMP_NOT83:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] -// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT83]], i1 false, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT159:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT159]], i1 false, !annotation [[META3]] // CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META14:![0-9]+]] // CHECK-NEXT: unreachable, !annotation [[META14]] // CHECK: land.rhs: -// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT60:%.*]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT133:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CMP54:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] -// CHECK-NEXT: [[CMP57:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] -// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP57]], [[CMP54]] -// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT60]], label [[TRAP]], !prof [[PROF11]], !annotation [[META3]] -// CHECK: cont60: +// CHECK-NEXT: [[CMP56:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] +// CHECK-NEXT: [[CMP59:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP59]], [[CMP56]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT133]], label [[TRAP]], !prof [[PROF11]], !annotation [[META3]] +// CHECK: cont133: // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] // CHECK-NEXT: ret ptr [[TMP0]] @@ -204,5 +203,5 @@ int *__counted_by_or_null(len) caller_10(int len) { // CHECK: [[PROF11]] = !{!"branch_weights", i32 1048575, i32 1} // CHECK: [[PROF12]] = !{!"branch_weights", i32 2097151, i32 1} // CHECK: [[META13]] = !{!"bounds-safety-zero-init"} -// CHECK: [[META14]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} +// CHECK: [[META14]] = !{!"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} //. diff --git a/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call.c b/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call.c index b6500d60d6a68..79399946712a7 100644 --- a/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call.c +++ b/clang/test/BoundsSafety/CodeGen/counted_by_or_null_call.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s @@ -10,10 +9,10 @@ void foo(int *__counted_by_or_null(len) p, int len); // CHECK-LABEL: define dso_local void @caller_1( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2:![0-9]+]], !annotation [[META3:![0-9]+]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 2) // CHECK-NEXT: ret void @@ -25,10 +24,10 @@ void caller_1() { // CHECK-LABEL: define dso_local void @caller_2( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 0) // CHECK-NEXT: ret void @@ -55,8 +54,8 @@ void caller_2() { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDX_EXT]] @@ -77,98 +76,98 @@ void caller_2() { // CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] // CHECK: boundscheck.cont: // CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META3]] // CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META3]] // CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] -// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META3]] // CHECK: land.rhs53: -// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META3]] // CHECK: land.end: // CHECK-NEXT: [[TMP13:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META3]] // CHECK: lor.end: // CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP13]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META3]] // CHECK: land.end56: -// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP14]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP14]], [[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 @@ -198,10 +197,10 @@ void caller_3(int *__counted_by_or_null(len) p, int len) { // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 -// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 @@ -232,10 +231,10 @@ void caller_4() { // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 -// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 @@ -279,98 +278,98 @@ void caller_5() { // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META3]] // CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META3]] // CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] -// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP8]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META3]] // CHECK: land.rhs53: -// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META3]] // CHECK: land.end: // CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META3]] // CHECK: lor.end: // CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP9]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META3]] // CHECK: land.end56: -// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP10]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP10]], [[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 @@ -404,98 +403,98 @@ void caller_6(int *__counted_by(len) p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END56:%.*]], !annotation [[META3]] // CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END56]], !annotation [[META3]] // CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] -// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB37]], ptr [[TMP3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR39]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP51:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP51]], label [[LAND_RHS53:%.*]], label [[LAND_END:%.*]], !annotation [[META3]] // CHECK: land.rhs53: -// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK-NEXT: [[CMP54:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META3]] // CHECK: land.end: // CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP54]], [[LAND_RHS53]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META3]] // CHECK: lor.end: // CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP4]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END56]], !annotation [[META3]] // CHECK: land.end56: -// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP5]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP5]], [[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 @@ -523,88 +522,88 @@ void caller_7(int *__bidi_indexable p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END29:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END29:%.*]], !annotation [[META3]] // CHECK: land.lhs.true: -// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP13]], label [[LAND_RHS:%.*]], label [[LAND_END29]], !annotation [[META2]] +// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP13]], label [[LAND_RHS:%.*]], label [[LAND_END29]], !annotation [[META3]] // CHECK: land.rhs: -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[UPPER15:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER15]], ptr [[TMP11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB17]], ptr [[TMP13]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR19]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] -// CHECK-NEXT: [[CMP24:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP24]], label [[LAND_RHS26:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[UPPER15:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER15]], ptr [[TMP11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB17]], ptr [[TMP13]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR19]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP24:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP24]], label [[LAND_RHS26:%.*]], label [[LAND_END:%.*]], !annotation [[META3]] // CHECK: land.rhs26: -// CHECK-NEXT: [[CMP27:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META3]] // CHECK: land.end: // CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP27]], [[LAND_RHS26]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META3]] // CHECK: lor.end: // CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP14]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END29]], !annotation [[META2]] +// CHECK-NEXT: br label [[LAND_END29]], !annotation [[META3]] // CHECK: land.end29: -// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP15]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP15]], [[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: // CHECK-NEXT: call void @foo(ptr noundef [[TMP0]], i32 noundef [[TMP1]]) // CHECK-NEXT: ret void @@ -640,20 +639,28 @@ void caller_9(int *__counted_by(*len) *out, int *len){ // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP65:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP72:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP23:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP30:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP54:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP69:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP81:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP94:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP97:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP107:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP117:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP120:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP141:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] -// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META4]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META5:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META5]] // CHECK-NEXT: [[TMP0:%.*]] = getelementptr ptr, ptr [[P]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[P]], ptr [[TMP1]], align 8 @@ -675,176 +682,261 @@ void caller_9(int *__counted_by(*len) *out, int *len){ // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP8]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP8]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT6:%.*]], !annotation [[META4]] // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], !annotation [[META5:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr ptr, ptr [[WIDE_PTR_PTR]], i64 1, !annotation [[META6:![0-9]+]] +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF2]], !annotation [[META6]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] -// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] // CHECK: cont: -// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META6:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !annotation [[META6]] +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF2]], !annotation [[META6]] // CHECK: trap3: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] // CHECK-NEXT: unreachable, !annotation [[META6]] // CHECK: cont4: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL12:%.*]], label [[CONT16:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull12: -// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_UB9]], !annotation [[META5]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !annotation [[META5]] -// CHECK: trap13: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] -// CHECK-NEXT: unreachable, !annotation [[META5]] -// CHECK: cont14: -// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT16]], label [[TRAP15:%.*]], !annotation [[META6]] +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT6]], label [[TRAP5:%.*]], !prof [[PROF2]], !annotation [[META7]] +// CHECK: trap5: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: cont6: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR9]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL14:%.*]], label [[CONT20:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull14: +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR9]], i64 1, !annotation [[META6]] +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB11]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT16:%.*]], label [[TRAP15:%.*]], !prof [[PROF2]], !annotation [[META6]] // CHECK: trap15: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] // CHECK-NEXT: unreachable, !annotation [[META6]] // CHECK: cont16: -// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR7]]) -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP14]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL18:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull18: -// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP15]] to i64 -// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_PTR9]], [[TMP14]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !prof [[PROF2]], !annotation [[META6]] +// CHECK: trap17: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: cont18: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR9]], [[WIDE_PTR_LB13]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT20]], label [[TRAP19:%.*]], !prof [[PROF2]], !annotation [[META7]] +// CHECK: trap19: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: cont20: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR9]]) +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP20:%.*]] = icmp ne ptr [[TMP18]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP20]], label [[BOUNDSCHECK_NOTNULL22:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull22: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP19]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP23]], align 8 // CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] // CHECK: boundscheck.null: -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 -// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP26]], align 8 // CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] // CHECK: boundscheck.cont: -// CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR21]], [[WIDE_PTR_UB28]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END62:%.*]], !annotation [[META2]] +// CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP23]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR25:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR24]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB27:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR26]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB29:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR28]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP30]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_UB32]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END66:%.*]], !annotation [[META3]] // CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP39:%.*]] = icmp ule ptr [[WIDE_PTR_LB31]], [[WIDE_PTR_PTR34]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP39]], label [[LAND_RHS:%.*]], label [[LAND_END62]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_LB35]], [[WIDE_PTR_PTR38]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP43]], label [[LAND_RHS:%.*]], label [[LAND_END66]], !annotation [[META3]] // CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR42]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR46]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP23]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP47]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB49]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR52]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META2]] -// CHECK-NEXT: [[CMP57:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP57]], label [[LAND_RHS59:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs59: -// CHECK-NEXT: [[CMP60:%.*]] = icmp sle i32 0, [[TMP23]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP27]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP54]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR56:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR55]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB58:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR57]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB60:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR59]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB53]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR56]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP61:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP61]], label [[LAND_RHS63:%.*]], label [[LAND_END:%.*]], !annotation [[META3]] +// CHECK: land.rhs63: +// CHECK-NEXT: [[CMP64:%.*]] = icmp sle i32 0, [[TMP27]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END]], !annotation [[META3]] // CHECK: land.end: -// CHECK-NEXT: [[TMP24:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP60]], [[LAND_RHS59]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] +// CHECK-NEXT: [[TMP28:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP64]], [[LAND_RHS63]] ] +// CHECK-NEXT: br label [[LOR_END]], !annotation [[META3]] // CHECK: lor.end: -// CHECK-NEXT: [[TMP25:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP24]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END62]], !annotation [[META2]] -// CHECK: land.end62: -// CHECK-NEXT: [[TMP26:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP25]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP26]], label [[CONT64:%.*]], label [[TRAP63:%.*]], !annotation [[META2]] -// CHECK: trap63: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont64: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP65]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR66:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR67:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR66]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR68:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB69:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR68]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP65]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB71:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR70]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR67]], ptr [[P]], align 8 -// CHECK-NEXT: store i32 [[TMP23]], ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP27:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP29:%.*]] = icmp ne ptr [[TMP27]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP29]], label [[BOUNDSCHECK_NOTNULL73:%.*]], label [[BOUNDSCHECK_NULL76:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull73: -// CHECK-NEXT: [[IDX_EXT74:%.*]] = sext i32 [[TMP28]] to i64 -// CHECK-NEXT: [[ADD_PTR75:%.*]] = getelementptr inbounds i32, ptr [[TMP27]], i64 [[IDX_EXT74]] -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP30]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR75]], ptr [[TMP31]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP32]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT77:%.*]] -// CHECK: boundscheck.null76: -// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP33]], align 8 -// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP34]], align 8 -// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 -// CHECK-NEXT: store ptr null, ptr [[TMP35]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT77]] -// CHECK: boundscheck.cont77: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR79:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR78]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB81:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR80]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB83:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR82]], align 8 -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR79]] +// CHECK-NEXT: [[TMP29:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP28]], [[LAND_END]] ] +// CHECK-NEXT: br label [[LAND_END66]], !annotation [[META3]] +// CHECK: land.end66: +// CHECK-NEXT: [[TMP30:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP29]], [[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP30]], label [[CONT68:%.*]], label [[TRAP67:%.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: trap67: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont68: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP69]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP69]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR71:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR70]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP69]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB73:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP69]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB75:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR74]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR71]], ptr [[P]], align 8 +// CHECK-NEXT: store i32 [[TMP27]], ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP31:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP33:%.*]] = icmp ne ptr [[TMP31]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP33]], label [[BOUNDSCHECK_NOTNULL76:%.*]], label [[BOUNDSCHECK_NULL79:%.*]], !annotation [[META4]] +// CHECK: boundscheck.notnull76: +// CHECK-NEXT: [[IDX_EXT77:%.*]] = sext i32 [[TMP32]] to i64 +// CHECK-NEXT: [[ADD_PTR78:%.*]] = getelementptr inbounds i32, ptr [[TMP31]], i64 [[IDX_EXT77]] +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP31]], ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR78]], ptr [[TMP35]], align 8 +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP31]], ptr [[TMP36]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT80:%.*]] +// CHECK: boundscheck.null79: +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP39]], align 8 +// CHECK-NEXT: br label [[BOUNDSCHECK_CONT80]] +// CHECK: boundscheck.cont80: +// CHECK-NEXT: [[TMP40:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP81]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR83:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR82]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB85:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR84]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR86:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB87:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR86]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP88]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP88]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB90:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR89]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP91:%.*]] = icmp ule ptr [[WIDE_PTR_PTR83]], [[WIDE_PTR_UB90]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP91]], label [[LAND_LHS_TRUE93:%.*]], label [[LAND_END138:%.*]], !annotation [[META3]] +// CHECK: land.lhs.true93: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP94]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR95:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP94]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB96:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR95]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP97]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP97]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR99:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR98]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP97]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB101:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR100]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP97]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB103:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR102]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP104:%.*]] = icmp ule ptr [[WIDE_PTR_LB96]], [[WIDE_PTR_PTR99]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP104]], label [[LAND_RHS106:%.*]], label [[LAND_END138]], !annotation [[META3]] +// CHECK: land.rhs106: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP107]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR108:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP107]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR109:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR108]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR110:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP107]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB111:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR110]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR112:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP107]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB113:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR112]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL114:%.*]] = icmp ne ptr [[WIDE_PTR_PTR109]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL114]], label [[LOR_RHS115:%.*]], label [[LOR_END137:%.*]], !annotation [[META3]] +// CHECK: lor.rhs115: +// CHECK-NEXT: [[CONV116:%.*]] = sext i32 [[TMP40]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP117]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR118:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP117]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB119:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR118]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP120]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR121:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP120]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR122:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR121]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR123:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP120]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB124:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR123]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR125:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP120]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB126:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR125]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST127:%.*]] = ptrtoint ptr [[WIDE_PTR_UB119]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST128:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR122]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB129:%.*]] = sub i64 [[SUB_PTR_LHS_CAST127]], [[SUB_PTR_RHS_CAST128]], !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_DIV130:%.*]] = sdiv exact i64 [[SUB_PTR_SUB129]], 4, !annotation [[META3]] +// CHECK-NEXT: [[CMP131:%.*]] = icmp sle i64 [[CONV116]], [[SUB_PTR_DIV130]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP131]], label [[LAND_RHS133:%.*]], label [[LAND_END136:%.*]], !annotation [[META3]] +// CHECK: land.rhs133: +// CHECK-NEXT: [[CMP134:%.*]] = icmp sle i32 0, [[TMP40]], !annotation [[META3]] +// CHECK-NEXT: br label [[LAND_END136]], !annotation [[META3]] +// CHECK: land.end136: +// CHECK-NEXT: [[TMP41:%.*]] = phi i1 [ false, [[LOR_RHS115]] ], [ [[CMP134]], [[LAND_RHS133]] ] +// CHECK-NEXT: br label [[LOR_END137]], !annotation [[META3]] +// CHECK: lor.end137: +// CHECK-NEXT: [[TMP42:%.*]] = phi i1 [ true, [[LAND_RHS106]] ], [ [[TMP41]], [[LAND_END136]] ] +// CHECK-NEXT: br label [[LAND_END138]], !annotation [[META3]] +// CHECK: land.end138: +// CHECK-NEXT: [[TMP43:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE93]] ], [ false, [[BOUNDSCHECK_CONT80]] ], [ [[TMP42]], [[LOR_END137]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP43]], label [[CONT140:%.*]], label [[TRAP139:%.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: trap139: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: cont140: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP141]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR142:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP141]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR143:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR142]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR144:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP141]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB145:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR144]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR146:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP141]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB147:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR146]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR143]] // int *__counted_by_or_null(len) caller_10(int len) { int count; @@ -855,9 +947,10 @@ int *__counted_by_or_null(len) caller_10(int len) { return p; } //. -// CHECK: [[META2]] = !{!"bounds-safety-generic"} -// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} -// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} -// CHECK: [[META5]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} -// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[PROF2]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META3]] = !{!"bounds-safety-generic"} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META5]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[META7]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/counted_by_to_counted_by-O2.c b/clang/test/BoundsSafety/CodeGen/counted_by_to_counted_by-O2.c index 1e776843b365f..567809da98c77 100644 --- a/clang/test/BoundsSafety/CodeGen/counted_by_to_counted_by-O2.c +++ b/clang/test/BoundsSafety/CodeGen/counted_by_to_counted_by-O2.c @@ -25,7 +25,7 @@ int *__sized_by(siz) my_alloc_int_siz(int siz); // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef 9) #[[ATTR4:[0-9]+]] // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestCountIntFail(void) { struct Packet p; @@ -38,7 +38,7 @@ void TestCountIntFail(void) { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestCountNegFail(void) { struct Packet p; @@ -51,7 +51,7 @@ void TestCountNegFail(void) { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestUCountNegFail(void) { struct PacketUnsigned p; @@ -63,8 +63,17 @@ void TestUCountNegFail(void) { // CHECK-LABEL: @TestCountNegRetFail( // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int(i32 noundef -1) #[[ATTR4]] +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 -4 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[CALL]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[CALL]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: +// CHECK-NEXT: ret void // void TestCountNegRetFail(void) { int *local_p = my_alloc_int(-1); //rdar://80808704 @@ -87,7 +96,7 @@ void TestCountIntOK(void) { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc(i32 noundef 39) #[[ATTR4]] // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestSizeFail(void) { struct Packet p; @@ -112,7 +121,7 @@ void TestSizeOK(void) { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @my_alloc_int_siz(i32 noundef 39) #[[ATTR4]] // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void TestIntSizeFail(void) { struct Packet p; diff --git a/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls-O2.c b/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls-O2.c index 3fe7525c16289..58dd823fef070 100644 --- a/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls-O2.c +++ b/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls-O2.c @@ -24,8 +24,8 @@ void success() { // CHECK-LABEL: @fail( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation !{{[0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META2]] // void fail() { int arr[10]; @@ -36,11 +36,11 @@ void fail() { // CHECK-LABEL: @pass_out_len( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUT_LEN:%.*]], align 4, !tbaa [[TBAA3:![0-9]+]] -// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[TMP0]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT:%.*]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[TMP0]], 0, !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !annotation [[META7]] // CHECK: trap: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation !{{[0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] // CHECK: cont: // CHECK-NEXT: ret void // @@ -50,12 +50,12 @@ void pass_out_len(int *__counted_by(*out_len) arr, int *out_len) { // CHECK-LABEL: @pass_addr_of_len( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[LEN:%.*]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT77:%.*]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[LEN:%.*]], 0, !annotation [[META7]] +// CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[CONT79:%.*]], !annotation [[META7]] // CHECK: trap: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation !{{[0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont77: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: cont79: // CHECK-NEXT: ret void // void pass_addr_of_len(int *__counted_by(len) arr, int len) { diff --git a/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls.c b/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls.c index ba4b20f23c87a..9c8394a7fa16c 100644 --- a/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls.c +++ b/clang/test/BoundsSafety/CodeGen/dynamic-inout-count-calls.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -22,14 +21,14 @@ void f_inout_count(int *__counted_by(*out_len) buf, int *out_len) {} // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP31:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP49:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP64:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP71:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP73:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: store ptr [[ARR:%.*]], ptr [[ARR_ADDR]], align 8 // CHECK-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARR_ADDR]], align 8 @@ -56,129 +55,143 @@ void f_inout_count(int *__counted_by(*out_len) buf, int *out_len) {} // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap3: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont4: -// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP11]] to i64 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB14:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR13]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: store ptr [[WIDE_PTR_UB14]], ptr [[TMP12]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END61:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap5: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont6: +// CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP13]] to i64 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB16]], ptr [[TMP14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR18:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB20:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB22:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR9]], [[WIDE_PTR_PTR18]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END63:%.*]], {{!annotation ![0-9]+}} // CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: store ptr [[WIDE_PTR_LB24]], ptr [[TMP13]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP22]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP31]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR33:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR32]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB35:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR34]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB37:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR36]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP38:%.*]] = icmp ule ptr [[WIDE_PTR_PTR26]], [[WIDE_PTR_PTR33]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP38]], label [[LAND_RHS:%.*]], label [[LAND_END61]], {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB26]], ptr [[TMP15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP40:%.*]] = icmp ule ptr [[WIDE_PTR_PTR28]], [[WIDE_PTR_PTR35]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP40]], label [[LAND_RHS:%.*]], label [[LAND_END63]], {{!annotation ![0-9]+}} // CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP14]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR44:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR43]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB46:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR45]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB48:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR47]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP49]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB55:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR54]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR44]] to i64, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR51]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP42]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB44]], ptr [[TMP16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR53]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP56:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP56]], label [[LAND_RHS58:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} -// CHECK: land.rhs58: -// CHECK-NEXT: [[CMP59:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP58:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP58]], label [[LAND_RHS60:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} +// CHECK: land.rhs60: +// CHECK-NEXT: [[CMP61:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} // CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} // CHECK: land.end: -// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_RHS]] ], [ [[CMP59]], [[LAND_RHS58]] ] -// CHECK-NEXT: br label [[LAND_END61]], {{!annotation ![0-9]+}} -// CHECK: land.end61: -// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[CONT4]] ], [ [[TMP15]], [[LAND_END]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT63:%.*]], label [[TRAP62:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap62: +// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[LAND_RHS]] ], [ [[CMP61]], [[LAND_RHS60]] ] +// CHECK-NEXT: br label [[LAND_END63]], {{!annotation ![0-9]+}} +// CHECK: land.end63: +// CHECK-NEXT: [[TMP18:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[CONT6]] ], [ [[TMP17]], [[LAND_END]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT65:%.*]], label [[TRAP64:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap64: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont63: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP64]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR66:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR65]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB68:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR67]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP64]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB70:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR69]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 -// CHECK-NEXT: [[TMP17:%.*]] = icmp ne ptr [[WIDE_PTR_PTR73]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP17]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT81:%.*]], {{!annotation ![0-9]+}} +// CHECK: cont65: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP66]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR68:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR67]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB70:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR69]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB72:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR71]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP73]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR75:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR74]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB77:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR76]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP73]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB79:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR78]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = icmp ne ptr [[WIDE_PTR_PTR75]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT85:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP18:%.*]] = icmp ult ptr [[WIDE_PTR_PTR73]], [[WIDE_PTR_UB75]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP18]], label [[CONT79:%.*]], label [[TRAP78:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap78: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont79: -// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR73]], [[WIDE_PTR_LB77]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP19]], label [[CONT81]], label [[TRAP80:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR75]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP21:%.*]] = icmp ule ptr [[TMP20]], [[WIDE_PTR_UB77]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP21]], label [[CONT81:%.*]], label [[TRAP80:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap80: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont81: -// CHECK-NEXT: call void @f_inout_count(ptr noundef [[WIDE_PTR_PTR66]], ptr noundef [[WIDE_PTR_PTR73]]) +// CHECK-NEXT: [[TMP22:%.*]] = icmp ule ptr [[WIDE_PTR_PTR75]], [[TMP20]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP22]], label [[CONT83:%.*]], label [[TRAP82:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap82: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont83: +// CHECK-NEXT: [[TMP23:%.*]] = icmp uge ptr [[WIDE_PTR_PTR75]], [[WIDE_PTR_LB79]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP23]], label [[CONT85]], label [[TRAP84:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap84: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont85: +// CHECK-NEXT: call void @f_inout_count(ptr noundef [[WIDE_PTR_PTR68]], ptr noundef [[WIDE_PTR_PTR75]]) // CHECK-NEXT: ret void // void pass_addr_of_len(int *__counted_by(len) arr, int len) { @@ -287,7 +300,7 @@ void pass_addr_of_len(int *__counted_by(len) arr, int len) { // CHECK-NEXT: br label [[LAND_END51]], {{!annotation ![0-9]+}} // CHECK: land.end51: // CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP11]], [[LAND_END]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} diff --git a/clang/test/BoundsSafety/CodeGen/ended_by_const_param-O2.c b/clang/test/BoundsSafety/CodeGen/ended_by_const_param-O2.c index 802d4e717a0b0..acc066930bad1 100644 --- a/clang/test/BoundsSafety/CodeGen/ended_by_const_param-O2.c +++ b/clang/test/BoundsSafety/CodeGen/ended_by_const_param-O2.c @@ -36,7 +36,7 @@ void good(void) { // CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[BOUND_PTR_ARITH]], [[UPPER]], !annotation [[META2:![0-9]+]] // CHECK-NEXT: [[CMP28_NOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], !annotation [[META2]] // CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP28_NOT]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !annotation [[META2]] // CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6:[0-9]+]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] @@ -60,7 +60,7 @@ void oob_upper(void) { // CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[BOUND_PTR_ARITH]], [[UPPER]], !annotation [[META2]] // CHECK-NEXT: [[CMP28_NOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], !annotation [[META2]] // CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP28_NOT]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP:.*]], label %[[CONT:.*]], !annotation [[META2]] // CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] @@ -86,5 +86,4 @@ void oob_order(void) { } //. // CHECK: [[META2]] = !{!"bounds-safety-generic"} -// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048577, i32 1048575} //. diff --git a/clang/test/BoundsSafety/CodeGen/ended_by_const_param.c b/clang/test/BoundsSafety/CodeGen/ended_by_const_param.c index b88fda158c69e..1aacea8382d47 100644 --- a/clang/test/BoundsSafety/CodeGen/ended_by_const_param.c +++ b/clang/test/BoundsSafety/CodeGen/ended_by_const_param.c @@ -39,9 +39,9 @@ void foo(int * const __ended_by(end) start, int* const end) { // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [40 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 40 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 @@ -72,40 +72,44 @@ void foo(int * const __ended_by(end) start, int* const end) { // CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP15]], align 8, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 1, !annotation [[META2]] // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR7]], !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, !annotation [[META2]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR9]], !annotation [[META2]] // CHECK-NEXT: br i1 [[CMP]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] // CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // CHECK: [[CONT]]: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR14:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR13]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB18:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR17]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8 -// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR14]], ptr noundef [[WIDE_PTR_PTR21]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP21]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR23:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8 +// CHECK-NEXT: call void @foo(ptr noundef [[WIDE_PTR_PTR16]], ptr noundef [[WIDE_PTR_PTR23]]) // CHECK-NEXT: ret void // void bar(void) { diff --git a/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr-O2.c b/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr-O2.c index 21a8f07466f45..90098b1ed01ed 100644 --- a/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr-O2.c +++ b/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -30,9 +29,8 @@ void ok(void) { // FIXME: rdar://105524069 // CHECK-LABEL: @start_fail_lower( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @ended_by_p, align 8, {{!tbaa ![0-9]+}} -// CHECK-NEXT: tail call void [[TMP0]](ptr noundef nonnull @x, ptr noundef nonnull getelementptr inbounds nuw (i8, ptr @x, i64 11)) #[[ATTR4]] -// CHECK-NEXT: ret void +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void start_fail_lower(void) { ended_by_p(x.array - 1, x.array + 10); @@ -40,7 +38,7 @@ void start_fail_lower(void) { // CHECK-LABEL: @start_fail_upper( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void start_fail_upper(void) { diff --git a/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr.c b/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr.c index da2cc39c7e57a..8090da2c0b8f0 100644 --- a/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr.c +++ b/clang/test/BoundsSafety/CodeGen/ended_by_func_ptr.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -18,9 +17,9 @@ ended_by_t ended_by_p = &ended_by; // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], ptr [[ARRAY]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY]], i64 10 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 @@ -50,42 +49,46 @@ ended_by_t ended_by_p = &ended_by; // CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 // CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr @ended_by_p, align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP12]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR14:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR13]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB16:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR15]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP12]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB18:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR17]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8 -// CHECK-NEXT: call void [[TMP15]](ptr noundef [[WIDE_PTR_PTR14]], ptr noundef [[WIDE_PTR_PTR21]]) +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr @ended_by_p, align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP21]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR23:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB25:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR24]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8 +// CHECK-NEXT: call void [[TMP16]](ptr noundef [[WIDE_PTR_PTR16]], ptr noundef [[WIDE_PTR_PTR23]]) // CHECK-NEXT: ret void // void foo(void) { diff --git a/clang/test/BoundsSafety/CodeGen/ended_by_returns.c b/clang/test/BoundsSafety/CodeGen/ended_by_returns.c index 4cbd26dad176a..00404f7db1f23 100644 --- a/clang/test/BoundsSafety/CodeGen/ended_by_returns.c +++ b/clang/test/BoundsSafety/CodeGen/ended_by_returns.c @@ -1,56 +1,124 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s #include // TODO: rdar://83900556 -// CHECK-LABEL: @chunk( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local ptr @chunk( +// CHECK-SAME: ptr noundef [[BEGIN:%.*]], ptr noundef [[END:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[BEGIN_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[END_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: store ptr [[BEGIN:%.*]], ptr [[BEGIN_ADDR]], align 8 -// CHECK-NEXT: store ptr [[END:%.*]], ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP_TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP6:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_ADDR]], align 8 +// CHECK-NEXT: store ptr [[END]], ptr [[END_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BEGIN_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[BEGIN_ADDR]], align 8 // CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[END_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 // CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 0 // CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 // CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP7]], i64 1 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 1 // CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP1]], i32 0, i32 2 // CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[BEGIN_ADDR]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[END_ADDR]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP20]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP_TMP2]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP6]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[TMP_TMP2]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP20:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_PTR15]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP20]], label %[[LAND_RHS:.*]], label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP21]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP24]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP31:%.*]] = icmp ule ptr [[WIDE_PTR_LB23]], [[WIDE_PTR_PTR26]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP21:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[CMP31]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP21]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR34]] // char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { return begin + 1; } -// CHECK-LABEL: @foo( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @foo( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 // CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -62,10 +130,10 @@ char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { // CHECK-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP38:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP46:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP53:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP60:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 @@ -119,86 +187,90 @@ char *__ended_by(end) chunk(char *__ended_by(end) begin, char *end) { // CHECK-NEXT: store ptr [[WIDE_PTR_UB10]], ptr [[TMP19]], align 8 // CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 // CHECK-NEXT: store ptr [[WIDE_PTR_LB12]], ptr [[TMP20]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8 -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 -// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_PTR38]] -// CHECK-NEXT: br label [[LAND_END]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP22:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP43]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR46]], ptr noundef [[WIDE_PTR_PTR53]]) -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP58]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP23]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP24]], align 8 -// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP25]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB31]], ptr [[TMP22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR33:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB35:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB37:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP38]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP45:%.*]] = icmp ule ptr [[WIDE_PTR_PTR33]], [[WIDE_PTR_PTR40]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP23:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP45]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP23]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP46]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR48:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR47]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB50:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR49]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB52:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR51]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP53]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR55:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB57:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR56]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB59:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR58]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR48]], ptr noundef [[WIDE_PTR_PTR55]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP60]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR62:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR61]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB64:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR63]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB66:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR65]], align 8 -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB64]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR64:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR63]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB66:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR65]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR64]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB68]], ptr [[TMP29]], align 8 // CHECK-NEXT: ret void // void foo(void) { @@ -206,8 +278,9 @@ void foo(void) { int *p = chunk(arr, arr+10); } -// CHECK-LABEL: @fooCast( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @fooCast( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 // CHECK-NEXT: [[P:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -219,10 +292,10 @@ void foo(void) { // CHECK-NEXT: [[AGG_TEMP13:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP20:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP38:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP46:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP53:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP60:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 @@ -276,89 +349,96 @@ void foo(void) { // CHECK-NEXT: store ptr [[WIDE_PTR_UB10]], ptr [[TMP19]], align 8 // CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 // CHECK-NEXT: store ptr [[WIDE_PTR_LB12]], ptr [[TMP20]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8 -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8 -// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_PTR38]] -// CHECK-NEXT: br label [[LAND_END]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP22:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP43]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP13]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP13]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR24]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB31]], ptr [[TMP22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR33:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB35:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR34]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB37:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR36]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP38]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP38]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP45:%.*]] = icmp ule ptr [[WIDE_PTR_PTR33]], [[WIDE_PTR_PTR40]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP23:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP45]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP23]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR46]], ptr noundef [[WIDE_PTR_PTR53]]) -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP58]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP23]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP24]], align 8 -// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP25]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP46]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR48:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR47]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB50:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR49]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP46]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB52:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR51]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP53]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR55:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB57:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR56]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP53]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB59:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR58]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @chunk(ptr noundef [[WIDE_PTR_PTR48]], ptr noundef [[WIDE_PTR_PTR55]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP60]], ptr align 8 [[AGG_TEMP3]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR62:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR61]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB64:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR63]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB66:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR65]], align 8 -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB64]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[CALL]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR64:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR63]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB66:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR65]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR64]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB66]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[P]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB68]], ptr [[TMP29]], align 8 // CHECK-NEXT: ret void // void fooCast(void) { int arr[10]; int *p = (int*)chunk(arr, arr+10); } +//. +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-assignment.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-assignment.c index 168085fa8b9c0..c9f47fdacbea9 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-assignment.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-assignment.c @@ -2,7 +2,6 @@ // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s - #include typedef struct { @@ -33,10 +32,10 @@ typedef struct { // CHECK: flex.base.nonnull: // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FLEX_T:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 @@ -47,32 +46,32 @@ typedef struct { // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: // CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: // CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 -// CHECK-NEXT: br i1 true, label [[CONT15:%.*]], label [[TRAP14:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 true, label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap14: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont15: // CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT17:%.*]], label [[TRAP16:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap16: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont17: // CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT19:%.*]], label [[TRAP18:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT19:%.*]], label [[TRAP18:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap18: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -82,7 +81,7 @@ typedef struct { // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 123, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT21]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT21]], label [[TRAP20:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap20: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -95,23 +94,30 @@ typedef struct { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8 // CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR23]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT31:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT33:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR23]], [[WIDE_PTR_UB25]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT29:%.*]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR23]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[TMP8]], [[WIDE_PTR_UB25]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT29:%.*]], label [[TRAP28:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap28: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont29: -// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR23]], [[WIDE_PTR_LB27]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT31]], label [[TRAP30:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_PTR23]], [[TMP8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT31:%.*]], label [[TRAP30:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap30: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont31: +// CHECK-NEXT: [[TMP11:%.*]] = icmp uge ptr [[WIDE_PTR_PTR23]], [[WIDE_PTR_LB27]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT33]], label [[TRAP32:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap32: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont33: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR23]], ptr [[FLEX_ADDR]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 -// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP10]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP12]], i32 0, i32 0 // CHECK-NEXT: store i32 123, ptr [[COUNT]], align 4 // CHECK-NEXT: ret void // diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-checks-no-count-O2.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-checks-no-count-O2.c index 4d4a35afafa57..df3d8dd3b2b78 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-checks-no-count-O2.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-checks-no-count-O2.c @@ -2,7 +2,6 @@ // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s - #include typedef struct { @@ -16,17 +15,17 @@ typedef struct { // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7:[0-9]+]] // CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -1 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[BOUND_PTR_ARITH]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[DOTNOT]], label [[CONT8:%.*]], label [[BOUNDSCHECK_NOTNULL:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[CONT9:%.*]], label [[BOUNDSCHECK_NOTNULL:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 20 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT8]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 3, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[BOUND_PTR_ARITH]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND10:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND10]], label [[CONT9]], label [[TRAP:%.*]], !prof [[PROF5:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont8: +// CHECK: cont9: // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] // CHECK-NEXT: ret void // @@ -53,7 +52,7 @@ void test_under_base_ok() { // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr nonnull [[ARR]]) #[[ATTR7]] // CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -1 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[ARR]], [[BOUND_PTR_ARITH]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], !prof [[PROF7:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -97,7 +96,7 @@ void test_over_base_ok() { // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 20 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 24 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT8:%.*]], !prof [[PROF7]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -115,6 +114,19 @@ void test_over_base_fail2() { // FIXME: rdar://84809738 // CHECK-LABEL: @test_small_base_fail( // CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 3 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT9:%.*]], label [[TRAP:%.*]], !prof [[PROF5]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] // CHECK-NEXT: ret void // void test_small_base_fail(flex_t *flex) { @@ -133,6 +145,19 @@ void test_small_base_ok() { // CHECK-LABEL: @test_small_base_fail2( // CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 3 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT9:%.*]], label [[TRAP:%.*]], !prof [[PROF5]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] // CHECK-NEXT: ret void // void test_small_base_fail2() { @@ -171,6 +196,19 @@ void test_count_from_buf_ok2(flex_t *flex) { // FIXME: rdar://84809738 // CHECK-LABEL: @test_count_from_buf_fail( // CHECK-NEXT: entry: +// CHECK-NEXT: [[ARR:%.*]] = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 3 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT9:%.*]], label [[TRAP:%.*]], !prof [[PROF5]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[ARR]]) #[[ATTR7]] // CHECK-NEXT: ret void // void test_count_from_buf_fail() { @@ -257,6 +295,19 @@ void test_flex_init_list_ok() { // FIXME: rdar://84809738 // CHECK-LABEL: @test_flex_init_list_fail( // CHECK-NEXT: entry: +// CHECK-NEXT: [[BUF:%.*]] = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 3 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BUF]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[BUF]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT10:%.*]], label [[TRAP:%.*]], !prof [[PROF5]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont10: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] // CHECK-NEXT: ret void // void test_flex_init_list_fail() { @@ -286,6 +337,16 @@ void test_flex_argument_ok() { // CHECK-NEXT: entry: // CHECK-NEXT: [[BUF:%.*]] = alloca [3 x i8], align 1 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 3 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BUF]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[BUF]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT10:%.*]], label [[TRAP:%.*]], !prof [[PROF5]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR8]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont10: // CHECK-NEXT: call void @sink(ptr noundef nonnull [[BUF]]) #[[ATTR7]] // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr nonnull [[BUF]]) #[[ATTR7]] // CHECK-NEXT: ret void diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-const-call.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-const-call.c index db1a3befb30d7..451e4f5fddd03 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-const-call.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-const-call.c @@ -1,6 +1,5 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -8,8 +7,9 @@ unsigned data_const_global_count __unsafe_late_const; -// CHECK-LABEL: @get_const_count( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local i32 @get_const_count( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @data_const_global_count, align 4 // CHECK-NEXT: ret i32 [[TMP0]] // @@ -22,16 +22,17 @@ struct struct_flex { int fam[__counted_by(get_const_count())]; }; -// CHECK-LABEL: @test( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test( +// CHECK-SAME: ptr noundef [[FLEX:%.*]], ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[NEW_PTR:%.*]]) #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[FLEX_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: store ptr [[FLEX:%.*]], ptr [[FLEX_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[NEW_PTR:%.*]], i64 24, i1 false) +// CHECK-NEXT: store ptr [[FLEX]], ptr [[FLEX_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[NEW_PTR]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 @@ -52,15 +53,15 @@ struct struct_flex { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT28:%.*]], {{!annotation ![0-9]+}} -// CHECK: flex.base.nonnull: +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label %[[FLEX_BASE_NONNULL:.*]], label %[[CONT28:.*]], {{!annotation ![0-9]+}} +// CHECK: [[FLEX_BASE_NONNULL]]: // CHECK-NEXT: [[TMP3:%.*]] = getelementptr [[STRUCT_STRUCT_FLEX:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br i1 [[TMP4]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 @@ -70,49 +71,49 @@ struct struct_flex { // CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr [[STRUCT_STRUCT_FLEX]], ptr [[WIDE_PTR_PTR12]], i64 1 // CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB14]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT18:%.*]], label [[TRAP17:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap17: +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT18:.*]], label %[[TRAP17:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP17]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont18: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT18]]: // CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT20:%.*]], label [[TRAP19:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap19: +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT20:.*]], label %[[TRAP19:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP19]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont20: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT20]]: // CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCT_FLEX]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 // CHECK-NEXT: [[CALL:%.*]] = call i32 @get_const_count() #[[ATTR5:[0-9]+]] // CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[CALL]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap21: +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label %[[CONT22:.*]], label %[[TRAP21:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP21]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont22: +// CHECK: [[CONT22]]: // CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap23: +// CHECK-NEXT: br i1 [[TMP8]], label %[[CONT24:.*]], label %[[TRAP23:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP23]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont24: +// CHECK: [[CONT24]]: // CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap25: +// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT26:.*]], label %[[TRAP25:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP25]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont26: +// CHECK: [[CONT26]]: // CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[CALL]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT28]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap27: +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label %[[CONT28]], label %[[TRAP27:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP27]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont28: +// CHECK: [[CONT28]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8 @@ -121,23 +122,33 @@ struct struct_flex { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8 // CHECK-NEXT: [[TMP10:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT38:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_UB32]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT36:%.*]], label [[TRAP35:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap35: +// CHECK-NEXT: br i1 [[TMP10]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT40:.*]], {{!annotation ![0-9]+}} +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_STRUCT_FLEX]], ptr [[WIDE_PTR_PTR30]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB32]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT36:.*]], label %[[TRAP35:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP35]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont36: -// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT38]], label [[TRAP37:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap37: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT36]]: +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR30]], [[TMP11]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label %[[CONT38:.*]], label %[[TRAP37:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP37]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT38]]: +// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT40]], label %[[TRAP39:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP39]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont38: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT40]]: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR30]], ptr [[FLEX_ADDR]], align 8 // CHECK-NEXT: ret void // void test(struct struct_flex *flex, void *__bidi_indexable new_ptr) { flex = new_ptr; } +//. +// CHECK: [[PROF4]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-multiple-decls.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-multiple-decls.c index 5c6b2ad286a91..41d2efc171cae 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-multiple-decls.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-multiple-decls.c @@ -1,8 +1,7 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s - #include typedef struct { @@ -12,8 +11,9 @@ typedef struct { } S; -// CHECK-LABEL: @trap_len_too_big( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @trap_len_too_big( +// CHECK-SAME: ptr noundef [[S:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[ARR:%.*]] = alloca [40 x i8], align 1 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -21,9 +21,9 @@ typedef struct { // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 -// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: store ptr [[S:%.*]], ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[ARR]], i8 0, i64 40, i1 false) // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [40 x i8], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY]], i64 40 @@ -53,15 +53,15 @@ typedef struct { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT29:%.*]], {{!annotation ![0-9]+}} -// CHECK: flex.base.nonnull: +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label %[[FLEX_BASE_NONNULL:.*]], label %[[CONT29:.*]], {{!annotation ![0-9]+}} +// CHECK: [[FLEX_BASE_NONNULL]]: // CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_S:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP6]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP10]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 @@ -71,46 +71,46 @@ typedef struct { // CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr [[STRUCT_S]], ptr [[WIDE_PTR_PTR12]], i64 1 // CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[TMP8]], [[WIDE_PTR_UB14]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT18:%.*]], label [[TRAP17:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap17: +// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT18:.*]], label %[[TRAP17:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP17]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont18: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT18]]: // CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT20:%.*]], label [[TRAP19:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap19: +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT20:.*]], label %[[TRAP19:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP19]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont20: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT20]]: // CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 2 // CHECK-NEXT: [[ARRAYDECAY21:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM]], i64 0, i64 0 -// CHECK-NEXT: br i1 true, label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap22: +// CHECK-NEXT: br i1 true, label %[[CONT23:.*]], label %[[TRAP22:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP22]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont23: +// CHECK: [[CONT23]]: // CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[ARRAYDECAY21]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT25:%.*]], label [[TRAP24:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap24: +// CHECK-NEXT: br i1 [[TMP11]], label %[[CONT25:.*]], label %[[TRAP24:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP24]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont25: +// CHECK: [[CONT25]]: // CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT27:%.*]], label [[TRAP26:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap26: +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT27:.*]], label %[[TRAP26:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP26]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont27: +// CHECK: [[CONT27]]: // CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY21]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 9, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT29]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap28: +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label %[[CONT29]], label %[[TRAP28:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP28]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont29: +// CHECK: [[CONT29]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 @@ -119,77 +119,91 @@ typedef struct { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 // CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR31]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT39:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_UB33]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT37:%.*]], label [[TRAP36:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap36: +// CHECK-NEXT: br i1 [[TMP13]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT41:.*]], {{!annotation ![0-9]+}} +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr [[STRUCT_S]], ptr [[WIDE_PTR_PTR31]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB33]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT37:.*]], label %[[TRAP36:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP36]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont37: -// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_LB35]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT39]], label [[TRAP38:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap38: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT37]]: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_PTR31]], [[TMP14]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label %[[CONT39:.*]], label %[[TRAP38:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP38]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT39]]: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR31]], [[WIDE_PTR_LB35]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label %[[CONT41]], label %[[TRAP40:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP40]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont39: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT41]]: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR31]], ptr [[S_ADDR]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[S_ADDR]], align 8 -// CHECK-NEXT: [[OFFS:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP16]], i32 0, i32 1 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[OFFS:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 1 // CHECK-NEXT: store i32 2, ptr [[OFFS]], align 4 -// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[S_ADDR]], align 8 -// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP17]], i32 0, i32 0 +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP19]], i32 0, i32 0 // CHECK-NEXT: store i32 11, ptr [[LEN]], align 4 -// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[S_ADDR]], align 8 -// CHECK-NEXT: [[FAM41:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 2 -// CHECK-NEXT: [[ARRAYDECAY42:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM41]], i64 0, i64 0 -// CHECK-NEXT: [[FAM44:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 2 -// CHECK-NEXT: [[ARRAYDECAY45:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM44]], i64 0, i64 0 -// CHECK-NEXT: [[LEN46:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 0 -// CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[LEN46]], align 4 -// CHECK-NEXT: [[OFFS47:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP18]], i32 0, i32 1 -// CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[OFFS47]], align 4 -// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP19]], [[TMP20]] +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK-NEXT: [[FAM43:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP20]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY44:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM43]], i64 0, i64 0 +// CHECK-NEXT: [[FAM46:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP20]], i32 0, i32 2 +// CHECK-NEXT: [[ARRAYDECAY47:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM46]], i64 0, i64 0 +// CHECK-NEXT: [[LEN48:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP20]], i32 0, i32 0 +// CHECK-NEXT: [[TMP21:%.*]] = load i32, ptr [[LEN48]], align 4 +// CHECK-NEXT: [[OFFS49:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP20]], i32 0, i32 1 +// CHECK-NEXT: [[TMP22:%.*]] = load i32, ptr [[OFFS49]], align 4 +// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP21]], [[TMP22]] // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[SUB]] to i64 -// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY45]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP22]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP23]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB49]], ptr [[TMP24]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8 -// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ARRAYDECAY42]], ptr [[TMP25]], align 8 -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR51]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ARRAYDECAY42]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY47]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP20]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP20]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB51:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR50]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB51]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR53]], i64 0 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP40]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 -// CHECK-NEXT: [[TMP29:%.*]] = icmp ult ptr [[TMP28]], [[WIDE_PTR_UB55]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP29]], label [[CONT59:%.*]], label [[TRAP58:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap58: +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY44]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR53]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY44]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR55:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR54]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR55]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB57:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR56]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB59:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR58]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP31:%.*]] = icmp ule ptr [[TMP30]], [[WIDE_PTR_UB57]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP31]], label %[[CONT61:.*]], label %[[TRAP60:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP60]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont59: -// CHECK-NEXT: [[TMP30:%.*]] = icmp uge ptr [[TMP28]], [[WIDE_PTR_LB57]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP30]], label [[CONT61:%.*]], label [[TRAP60:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap60: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT61]]: +// CHECK-NEXT: [[TMP32:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP30]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP32]], label %[[CONT63:.*]], label %[[TRAP62:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP62]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont61: -// CHECK-NEXT: store i32 0, ptr [[TMP28]], align 4 +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT63]]: +// CHECK-NEXT: [[TMP33:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB59]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT65:.*]], label %[[TRAP64:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP64]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT65]]: +// CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4 // CHECK-NEXT: ret void // void trap_len_too_big(S *s) { @@ -200,3 +214,6 @@ void trap_len_too_big(S *s) { s->fam[0] = 0; } +//. +// CHECK: [[PROF4]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-assignment.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-assignment.c index b8bfbe3a14091..4797115336e97 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-assignment.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-assignment.c @@ -2,7 +2,6 @@ // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s - #include typedef struct { @@ -95,10 +94,10 @@ void pointer_assign(flex_t *flex) { // CHECK: flex.base.nonnull: // CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 @@ -109,16 +108,16 @@ void pointer_assign(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: // CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: // CHECK-NEXT: [[ELEMS14:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY15:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS14]], i64 0, i64 0 @@ -131,33 +130,33 @@ void pointer_assign(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB22:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR21]], align 8 // CHECK-NEXT: [[TMP14:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR18]], i64 1 // CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB20]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap23: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont24: // CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_LB22]], [[WIDE_PTR_PTR18]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap25: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont26: // CHECK-NEXT: [[COUNT27:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR18]], i32 0, i32 0 // CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[COUNT27]], align 4 // CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP17]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT29:%.*]], label [[TRAP28:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT29:%.*]], label [[TRAP28:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap28: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont29: // CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[ARRAYDECAY15]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP18]], label [[CONT31:%.*]], label [[TRAP30:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT31:%.*]], label [[TRAP30:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap30: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont31: // CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP19]], label [[CONT33:%.*]], label [[TRAP32:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT33:%.*]], label [[TRAP32:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap32: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -168,7 +167,7 @@ void pointer_assign(flex_t *flex) { // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP17]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT35]], label [[TRAP34:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT35]], label [[TRAP34:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap34: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -181,20 +180,27 @@ void pointer_assign(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8 // CHECK-NEXT: [[TMP20:%.*]] = icmp ne ptr [[WIDE_PTR_PTR37]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP20]], label [[BOUNDSCHECK_NOTNULL42:%.*]], label [[CONT46:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP20]], label [[BOUNDSCHECK_NOTNULL42:%.*]], label [[CONT48:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull42: -// CHECK-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR37]], [[WIDE_PTR_UB39]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP21]], label [[CONT44:%.*]], label [[TRAP43:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR37]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP22:%.*]] = icmp ule ptr [[TMP21]], [[WIDE_PTR_UB39]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP22]], label [[CONT44:%.*]], label [[TRAP43:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap43: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont44: -// CHECK-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR37]], [[WIDE_PTR_LB41]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP22]], label [[CONT46]], label [[TRAP45:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP23:%.*]] = icmp ule ptr [[WIDE_PTR_PTR37]], [[TMP21]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP23]], label [[CONT46:%.*]], label [[TRAP45:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap45: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont46: +// CHECK-NEXT: [[TMP24:%.*]] = icmp uge ptr [[WIDE_PTR_PTR37]], [[WIDE_PTR_LB41]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP24]], label [[CONT48]], label [[TRAP47:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap47: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont48: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR37]], ptr [[S]], align 8 // CHECK-NEXT: ret void // @@ -243,16 +249,16 @@ void pointer_assign_single(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: // CHECK-NEXT: [[COUNT3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 // CHECK-NEXT: store i32 10, ptr [[COUNT3]], align 4 @@ -310,10 +316,10 @@ void pointer_and_count_assign(flex_t *flex) { // CHECK: flex.base.nonnull: // CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 @@ -324,32 +330,32 @@ void pointer_and_count_assign(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: // CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: // CHECK-NEXT: [[ELEMS14:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY15:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS14]], i64 0, i64 0 -// CHECK-NEXT: br i1 true, label [[CONT17:%.*]], label [[TRAP16:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 true, label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap16: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont17: // CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[ARRAYDECAY15]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT19:%.*]], label [[TRAP18:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT19:%.*]], label [[TRAP18:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap18: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont19: // CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT21:%.*]], label [[TRAP20:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap20: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -359,7 +365,7 @@ void pointer_and_count_assign(flex_t *flex) { // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 10, [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT23]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT23]], label [[TRAP22:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap22: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -372,24 +378,31 @@ void pointer_and_count_assign(flex_t *flex) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB29:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR28]], align 8 // CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[WIDE_PTR_PTR25]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL30:%.*]], label [[CONT34:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL30:%.*]], label [[CONT36:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull30: -// CHECK-NEXT: [[TMP17:%.*]] = icmp ult ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_UB27]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP17]], label [[CONT32:%.*]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR25]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[TMP17]], [[WIDE_PTR_UB27]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT32:%.*]], label [[TRAP31:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap31: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont32: -// CHECK-NEXT: [[TMP18:%.*]] = icmp uge ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_LB29]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP18]], label [[CONT34]], label [[TRAP33:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP19:%.*]] = icmp ule ptr [[WIDE_PTR_PTR25]], [[TMP17]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT34:%.*]], label [[TRAP33:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap33: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont34: +// CHECK-NEXT: [[TMP20:%.*]] = icmp uge ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_LB29]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP20]], label [[CONT36]], label [[TRAP35:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap35: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont36: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR25]], ptr [[B]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[B]], align 8 -// CHECK-NEXT: [[COUNT35:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP19]], i32 0, i32 0 -// CHECK-NEXT: store i32 10, ptr [[COUNT35]], align 4 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[COUNT37:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP21]], i32 0, i32 0 +// CHECK-NEXT: store i32 10, ptr [[COUNT37]], align 4 // CHECK-NEXT: ret void // void pointer_and_count_assign_single(flex_t *flex) { diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-deref.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-deref.c index 8720b9ada9973..22097087c2d6c 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-deref.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-deref.c @@ -2,7 +2,6 @@ // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s - #include typedef struct { @@ -40,10 +39,10 @@ flex_t g_flex = {2, {1, 2}}; // CHECK: flex.base.nonnull: // CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 @@ -54,16 +53,16 @@ flex_t g_flex = {2, {1, 2}}; // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: // CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: // CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 @@ -76,33 +75,33 @@ flex_t g_flex = {2, {1, 2}}; // CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 // CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i64 1 // CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap21: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont22: // CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_LB20]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap23: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont24: // CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i32 0, i32 0 // CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[COUNT]], align 4 // CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP12]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap25: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont26: // CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT28:%.*]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT28:%.*]], label [[TRAP27:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap27: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont28: // CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT30:%.*]], label [[TRAP29:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT30:%.*]], label [[TRAP29:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap29: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -113,7 +112,7 @@ flex_t g_flex = {2, {1, 2}}; // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP12]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap31: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -126,20 +125,27 @@ flex_t g_flex = {2, {1, 2}}; // CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 // CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[WIDE_PTR_PTR34]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT42:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT44:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP16:%.*]] = icmp ult ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT40:%.*]], label [[TRAP39:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR34]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP17:%.*]] = icmp ule ptr [[TMP16]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT40:%.*]], label [[TRAP39:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap39: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont40: -// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP17]], label [[CONT42]], label [[TRAP41:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[WIDE_PTR_PTR34]], [[TMP16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT42:%.*]], label [[TRAP41:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap41: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont42: +// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT44]], label [[TRAP43:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap43: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont44: // CHECK-NEXT: ret ptr [[WIDE_PTR_PTR34]] // flex_t *addrof_g(void) { @@ -151,7 +157,7 @@ flex_t *addrof_g(void) { // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca [[STRUCT_FLEX_T:%.*]], align 4 // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @g_flex, align 4 // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds nuw ([[STRUCT_FLEX_T]], ptr @g_flex, i32 0, i32 1), i64 [[IDX_EXT]] @@ -167,66 +173,80 @@ flex_t *addrof_g(void) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap3: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont4: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap5: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont6: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[AGG_TEMP1]], ptr align 4 [[WIDE_PTR_PTR]], i64 4, i1 false) // CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 -// CHECK-NEXT: [[ELEMS6:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY7:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS6]], i64 0, i64 0 +// CHECK-NEXT: [[ELEMS8:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY9:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS8]], i64 0, i64 0 // CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP1]], i32 0, i32 0 -// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[IDX_EXT8:%.*]] = sext i32 [[TMP6]] to i64 -// CHECK-NEXT: [[ADD_PTR9:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY7]], i64 [[IDX_EXT8]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[AGG_TEMP1]], ptr [[TMP7]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR9]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[IDX_EXT10:%.*]] = sext i32 [[TMP8]] to i64 +// CHECK-NEXT: [[ADD_PTR11:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY9]], i64 [[IDX_EXT10]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 // CHECK-NEXT: store ptr [[AGG_TEMP1]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB11]], ptr [[TMP10]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP11]], align 8 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP12]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP13]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR11]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[AGG_TEMP1]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB13:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR12]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB13]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR15]], i64 0 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = icmp ult ptr [[TMP14]], [[WIDE_PTR_UB17]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT21:%.*]], label [[TRAP20:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap20: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont21: -// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[TMP14]], [[WIDE_PTR_LB19]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT23:%.*]], label [[TRAP22:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR15]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR17:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR16]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR17]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB19:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR18]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB21:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR20]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP17:%.*]] = icmp ule ptr [[TMP16]], [[WIDE_PTR_UB19]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT23:%.*]], label [[TRAP22:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap22: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont23: -// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP14]], align 4 -// CHECK-NEXT: ret i32 [[TMP17]] +// CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT25:%.*]], label [[TRAP24:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap24: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont25: +// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB21]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT27:%.*]], label [[TRAP26:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap26: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont27: +// CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP20]] // int addrof_deref_g(void) { return (*&g_flex).elems[0]; @@ -241,10 +261,10 @@ int addrof_deref_g(void) { // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca [[STRUCT_FLEX_T:%.*]], align 4 -// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP62:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP46:%.*]] = alloca [[STRUCT_FLEX_T:%.*]], align 4 +// CHECK-NEXT: [[AGG_TEMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: store ptr [[P:%.*]], ptr [[P_INDIRECT_ADDR]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) @@ -259,10 +279,10 @@ int addrof_deref_g(void) { // CHECK: flex.base.nonnull: // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 @@ -273,16 +293,16 @@ int addrof_deref_g(void) { // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i64 1 // CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: // CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_LB9]], [[WIDE_PTR_PTR5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: // CHECK-NEXT: [[ELEMS:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR5]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS]], i64 0, i64 0 @@ -295,33 +315,33 @@ int addrof_deref_g(void) { // CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i64 1 // CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap21: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont22: // CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_LB20]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap23: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont24: // CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR16]], i32 0, i32 0 // CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[COUNT]], align 4 // CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP8]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap25: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont26: // CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT28:%.*]], label [[TRAP27:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT28:%.*]], label [[TRAP27:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap27: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont28: // CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT30:%.*]], label [[TRAP29:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT30:%.*]], label [[TRAP29:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap29: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -332,7 +352,7 @@ int addrof_deref_g(void) { // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = sdiv exact i64 [[FLEX_AVAIL_COUNT]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP8]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT32]], label [[TRAP31:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap31: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -345,112 +365,133 @@ int addrof_deref_g(void) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 // CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR34]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT42:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT44:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT40:%.*]], label [[TRAP39:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR34]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB36]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT40:%.*]], label [[TRAP39:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap39: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont40: -// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT42]], label [[TRAP41:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR34]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT42:%.*]], label [[TRAP41:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap41: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont42: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR34]], [[WIDE_PTR_LB38]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT44]], label [[TRAP43:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap43: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont44: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR34]], ptr [[FLEX]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[FLEX]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP14]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL46:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull46: -// CHECK-NEXT: [[ELEMS47:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP14]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY48:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS47]], i64 0, i64 0 -// CHECK-NEXT: [[COUNT49:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP14]], i32 0, i32 0 -// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[COUNT49]], align 4 -// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP16]] to i64 -// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY48]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[FLEX]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = icmp ne ptr [[TMP16]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[BOUNDSCHECK_NOTNULL48:%.*]], label [[BOUNDSCHECK_NULL:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull48: +// CHECK-NEXT: [[ELEMS49:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP16]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY50:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS49]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT51:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[TMP16]], i32 0, i32 0 +// CHECK-NEXT: [[TMP18:%.*]] = load i32, ptr [[COUNT51]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP18]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY50]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP16]], ptr [[TMP21]], align 8 // CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] // CHECK: boundscheck.null: -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP24]], align 8 // CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] // CHECK: boundscheck.cont: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB55:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR54]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = icmp ult ptr [[WIDE_PTR_PTR51]], [[WIDE_PTR_UB53]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP23]], label [[CONT57:%.*]], label [[TRAP56:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap56: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont57: -// CHECK-NEXT: [[TMP24:%.*]] = icmp uge ptr [[WIDE_PTR_PTR51]], [[WIDE_PTR_LB55]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP24]], label [[CONT59:%.*]], label [[TRAP58:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr [[STRUCT_FLEX_T]], ptr [[WIDE_PTR_PTR53]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP26:%.*]] = icmp ule ptr [[TMP25]], [[WIDE_PTR_UB55]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP26]], label [[CONT59:%.*]], label [[TRAP58:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap58: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont59: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[AGG_TEMP44]], ptr align 4 [[WIDE_PTR_PTR51]], i64 4, i1 false) -// CHECK-NEXT: [[ELEMS60:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY61:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS60]], i64 0, i64 0 -// CHECK-NEXT: [[ELEMS63:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY64:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS63]], i64 0, i64 0 -// CHECK-NEXT: [[COUNT65:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP44]], i32 0, i32 0 -// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[COUNT65]], align 4 -// CHECK-NEXT: [[IDX_EXT66:%.*]] = sext i32 [[TMP25]] to i64 -// CHECK-NEXT: [[ADD_PTR67:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY64]], i64 [[IDX_EXT66]] -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[AGG_TEMP44]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR67]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[AGG_TEMP44]], ptr [[TMP28]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR68:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB69:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR68]], align 8 -// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB69]], ptr [[TMP29]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP62]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR71:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR70]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ARRAYDECAY61]], ptr [[TMP30]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR71]], ptr [[TMP31]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ARRAYDECAY61]], ptr [[TMP32]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 -// CHECK-NEXT: [[TMP33:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR73]], i64 0 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB75:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR74]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB77:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR76]], align 8 -// CHECK-NEXT: [[TMP34:%.*]] = icmp ult ptr [[TMP33]], [[WIDE_PTR_UB75]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP34]], label [[CONT79:%.*]], label [[TRAP78:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap78: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont79: -// CHECK-NEXT: [[TMP35:%.*]] = icmp uge ptr [[TMP33]], [[WIDE_PTR_LB77]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP35]], label [[CONT81:%.*]], label [[TRAP80:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap80: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont81: -// CHECK-NEXT: store i32 10, ptr [[TMP33]], align 4 +// CHECK-NEXT: [[TMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR53]], [[TMP25]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP27]], label [[CONT61:%.*]], label [[TRAP60:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap60: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont61: +// CHECK-NEXT: [[TMP28:%.*]] = icmp uge ptr [[WIDE_PTR_PTR53]], [[WIDE_PTR_LB57]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP28]], label [[CONT63:%.*]], label [[TRAP62:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap62: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont63: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[AGG_TEMP46]], ptr align 4 [[WIDE_PTR_PTR53]], i64 4, i1 false) +// CHECK-NEXT: [[ELEMS64:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP46]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY65:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS64]], i64 0, i64 0 +// CHECK-NEXT: [[ELEMS67:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP46]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY68:%.*]] = getelementptr inbounds [0 x i32], ptr [[ELEMS67]], i64 0, i64 0 +// CHECK-NEXT: [[COUNT69:%.*]] = getelementptr inbounds nuw [[STRUCT_FLEX_T]], ptr [[AGG_TEMP46]], i32 0, i32 0 +// CHECK-NEXT: [[TMP29:%.*]] = load i32, ptr [[COUNT69]], align 4 +// CHECK-NEXT: [[IDX_EXT70:%.*]] = sext i32 [[TMP29]] to i64 +// CHECK-NEXT: [[ADD_PTR71:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY68]], i64 [[IDX_EXT70]] +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[AGG_TEMP46]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR71]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[AGG_TEMP46]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB73:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR72]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB73]], ptr [[TMP33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR75:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR74]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY65]], ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR75]], ptr [[TMP35]], align 8 +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY65]], ptr [[TMP36]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR77:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR76]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR77]], i64 0 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB79:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR78]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB81:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR80]], align 8 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP38:%.*]] = icmp ule ptr [[TMP37]], [[WIDE_PTR_UB79]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP38]], label [[CONT83:%.*]], label [[TRAP82:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap82: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont83: +// CHECK-NEXT: [[TMP39:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP37]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP39]], label [[CONT85:%.*]], label [[TRAP84:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap84: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont85: +// CHECK-NEXT: [[TMP40:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB81]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP40]], label [[CONT87:%.*]], label [[TRAP86:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap86: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont87: +// CHECK-NEXT: store i32 10, ptr [[ARRAYIDX]], align 4 // CHECK-NEXT: ret void // void assigning_array_single(flex_t *__bidi_indexable p) { diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-returns-O2.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-returns-O2.c index eaa2ca8388bbe..a86b95ece295f 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-returns-O2.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-promotion-returns-O2.c @@ -15,7 +15,7 @@ inline flex_t *return_flex(int *__counted_by(11) buf) { } // CHECK-LABEL: @pointer_assign_good( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: cont47: // CHECK-NEXT: ret void // void pointer_assign_good() { @@ -25,7 +25,7 @@ void pointer_assign_good() { } // CHECK-LABEL: @pointer_assign_good2( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: cont47: // CHECK-NEXT: ret void // void pointer_assign_good2() { @@ -35,7 +35,7 @@ void pointer_assign_good2() { } // CHECK-LABEL: @pointer_init_good( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: cont47: // CHECK-NEXT: ret void // void pointer_init_good() { @@ -44,7 +44,7 @@ void pointer_init_good() { } // CHECK-LABEL: @pointer_init_good2( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: cont47: // CHECK-NEXT: ret void // void pointer_init_good2() { @@ -53,9 +53,9 @@ void pointer_init_good2() { } // CHECK-LABEL: @pointer_count_assign_trap( -// CHECK-NEXT: {{.*}}: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void pointer_count_assign_trap() { int arr[11] = {10}; @@ -65,9 +65,9 @@ void pointer_count_assign_trap() { } // CHECK-LABEL: @pointer_count_init_trap( -// CHECK-NEXT: {{.*}}: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // void pointer_count_init_trap() { int arr[11] = {10}; @@ -76,7 +76,7 @@ void pointer_count_init_trap() { } // CHECK-LABEL: @pointer_count_assign_good( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: entry: // CHECK-NEXT: ret void // void pointer_count_assign_good() { @@ -87,7 +87,7 @@ void pointer_count_assign_good() { } // CHECK-LABEL: @pointer_count_init_good( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: entry: // CHECK-NEXT: ret void // void pointer_count_init_good() { @@ -97,7 +97,7 @@ void pointer_count_init_good() { } // CHECK-LABEL: @elem_access_good( -// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: cont69: // CHECK-NEXT: ret void // void elem_access_good() { @@ -108,9 +108,22 @@ void elem_access_good() { } // CHECK-LABEL: @elem_access_trap( -// CHECK-NEXT: {{.*}}: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: cont47: +// CHECK-NEXT: [[ARR:%.*]] = alloca [11 x i32], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 44, ptr nonnull [[ARR]]) #[[ATTR6:[0-9]+]] +// CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 44 +// CHECK-NEXT: [[AGG_TEMP_SROA_12_0_SROA_GEP87:%.*]] = getelementptr i8, ptr [[ARR]], i64 48 +// CHECK-NEXT: [[ADD_PTR56:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 44 +// CHECK-NEXT: [[TMP0:%.*]] = icmp ule ptr [[AGG_TEMP_SROA_12_0_SROA_GEP87]], [[ADD_PTR56]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[ADD_PTR_I]], [[AGG_TEMP_SROA_12_0_SROA_GEP87]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND75:%.*]] = and i1 [[TMP1]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND75]], label [[CONT69:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont69: +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 44, ptr nonnull [[ARR]]) #[[ATTR6]] +// CHECK-NEXT: ret void // void elem_access_trap() { int arr[11] = {10}; diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O0.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O0.c index ce6b0ddd7d76d..ad3f97073a936 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O0.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O0.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s #include @@ -34,8 +33,8 @@ int * __counted_by(len) baz(int len); // CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP80:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP82:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP90:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call ptr @baz(i32 noundef [[TMP0]]) @@ -195,85 +194,99 @@ int * __counted_by(len) baz(int len); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 // CHECK-NEXT: [[TMP18:%.*]] = icmp ne ptr [[WIDE_PTR_PTR70]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT78:.*]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT80:.*]], !annotation [[META4]] // CHECK: [[BOUNDSCHECK_NOTNULL]]: -// CHECK-NEXT: [[TMP19:%.*]] = icmp ult ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_UB72]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP19]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR70]], i64 1, !annotation [[META12:![0-9]+]] +// CHECK-NEXT: [[TMP20:%.*]] = icmp ule ptr [[TMP19]], [[WIDE_PTR_UB72]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP75]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] -// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] // CHECK: [[CONT76]]: -// CHECK-NEXT: [[TMP20:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] -// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT78]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK-NEXT: [[TMP21:%.*]] = icmp ule ptr [[WIDE_PTR_PTR70]], [[TMP19]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP21]], label %[[CONT78:.*]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP77]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT78]]: +// CHECK-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP22]], label %[[CONT80]], label %[[TRAP79:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP79]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] // CHECK-NEXT: unreachable, !annotation [[META7]] -// CHECK: [[CONT78]]: +// CHECK: [[CONT80]]: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[P]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP21]], i32 0, i32 0 -// CHECK-NEXT: [[LEN79:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 -// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN79]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP80]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR81:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR82:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR81]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB84:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR83]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP80]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB86:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR85]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[HDR87:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP22]], i32 0, i32 0 -// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR87]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR82]], ptr [[PTR]], align 8 // CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[TMP23]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP24]], label %[[BOUNDSCHECK_NOTNULL89:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] -// CHECK: [[BOUNDSCHECK_NOTNULL89]]: -// CHECK-NEXT: [[FAM90:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY91:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM90]], i64 0, i64 0 -// CHECK-NEXT: [[HDR92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 -// CHECK-NEXT: [[LEN93:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR92]], i32 0, i32 1 -// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[LEN93]], align 8 -// CHECK-NEXT: [[IDX_EXT94:%.*]] = sext i32 [[TMP25]] to i64 -// CHECK-NEXT: [[ADD_PTR95:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY91]], i64 [[IDX_EXT94]] -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR95]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 +// CHECK-NEXT: [[LEN81:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN81]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP82]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP82]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR84:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR83]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP82]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB86:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR85]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP82]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB88:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR87]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR89:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP24]], i32 0, i32 0 +// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR89]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR84]], ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = icmp ne ptr [[TMP25]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP26]], label %[[BOUNDSCHECK_NOTNULL91:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL91]]: +// CHECK-NEXT: [[FAM92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP25]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY93:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM92]], i64 0, i64 0 +// CHECK-NEXT: [[HDR94:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP25]], i32 0, i32 0 +// CHECK-NEXT: [[LEN95:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR94]], i32 0, i32 1 +// CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[LEN95]], align 8 +// CHECK-NEXT: [[IDX_EXT96:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK-NEXT: [[ADD_PTR97:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY93]], i64 [[IDX_EXT96]] +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR97]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP30]], align 8 // CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] // CHECK: [[BOUNDSCHECK_NULL]]: -// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP29]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP30]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP33]], align 8 // CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] // CHECK: [[BOUNDSCHECK_CONT]]: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR96:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR97:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR96]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB99:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR98]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB101:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR100]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[WIDE_PTR_PTR97]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP32]], label %[[BOUNDSCHECK_NOTNULL102:.*]], label %[[CONT106:.*]], !annotation [[META4]] -// CHECK: [[BOUNDSCHECK_NOTNULL102]]: -// CHECK-NEXT: [[TMP33:%.*]] = icmp ult ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_UB99]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT104:.*]], label %[[TRAP103:.*]], !prof [[PROF3]], !annotation [[META6]] -// CHECK: [[TRAP103]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] -// CHECK-NEXT: unreachable, !annotation [[META6]] -// CHECK: [[CONT104]]: -// CHECK-NEXT: [[TMP34:%.*]] = icmp uge ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_LB101]], !annotation [[META7]] -// CHECK-NEXT: br i1 [[TMP34]], label %[[CONT106]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR99:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR98]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB101:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR100]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB103:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR102]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = icmp ne ptr [[WIDE_PTR_PTR99]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP34]], label %[[BOUNDSCHECK_NOTNULL104:.*]], label %[[CONT110:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL104]]: +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR99]], i64 1, !annotation [[META12]] +// CHECK-NEXT: [[TMP36:%.*]] = icmp ule ptr [[TMP35]], [[WIDE_PTR_UB101]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP36]], label %[[CONT106:.*]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP105]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT106]]: +// CHECK-NEXT: [[TMP37:%.*]] = icmp ule ptr [[WIDE_PTR_PTR99]], [[TMP35]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP37]], label %[[CONT108:.*]], label %[[TRAP107:.*]], !prof [[PROF3]], !annotation [[META12]] +// CHECK: [[TRAP107]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT108]]: +// CHECK-NEXT: [[TMP38:%.*]] = icmp uge ptr [[WIDE_PTR_PTR99]], [[WIDE_PTR_LB103]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP38]], label %[[CONT110]], label %[[TRAP109:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP109]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] // CHECK-NEXT: unreachable, !annotation [[META7]] -// CHECK: [[CONT106]]: -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR97]] +// CHECK: [[CONT110]]: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR99]] // struct Outer *foo(int len) { int * p2 = baz(len); @@ -300,8 +313,8 @@ struct Outer *foo(int len) { // CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP79:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP81:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP90:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call ptr @baz(i32 noundef [[TMP0]]) @@ -461,85 +474,99 @@ struct Outer *foo(int len) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 // CHECK-NEXT: [[TMP18:%.*]] = icmp ne ptr [[WIDE_PTR_PTR70]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT78:.*]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT80:.*]], !annotation [[META4]] // CHECK: [[BOUNDSCHECK_NOTNULL]]: -// CHECK-NEXT: [[TMP19:%.*]] = icmp ult ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_UB72]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP19]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR70]], i64 1, !annotation [[META12]] +// CHECK-NEXT: [[TMP20:%.*]] = icmp ule ptr [[TMP19]], [[WIDE_PTR_UB72]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT76:.*]], label %[[TRAP75:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP75]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] -// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] // CHECK: [[CONT76]]: -// CHECK-NEXT: [[TMP20:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] -// CHECK-NEXT: br i1 [[TMP20]], label %[[CONT78]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK-NEXT: [[TMP21:%.*]] = icmp ule ptr [[WIDE_PTR_PTR70]], [[TMP19]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP21]], label %[[CONT78:.*]], label %[[TRAP77:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP77]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT78]]: +// CHECK-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR70]], [[WIDE_PTR_LB74]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP22]], label %[[CONT80]], label %[[TRAP79:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP79]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] // CHECK-NEXT: unreachable, !annotation [[META7]] -// CHECK: [[CONT78]]: +// CHECK: [[CONT80]]: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[P]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP79]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR81:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR80]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB83:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR82]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB85:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR84]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP21]], i32 0, i32 0 -// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR81]], ptr [[PTR]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[HDR86:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP22]], i32 0, i32 0 -// CHECK-NEXT: [[LEN87:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR86]], i32 0, i32 1 -// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN87]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP81]], ptr align 8 [[AGG_TEMP4]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR83:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR82]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB85:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR84]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR86:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP81]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB87:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR86]], align 8 // CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[TMP23]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP24]], label %[[BOUNDSCHECK_NOTNULL89:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] -// CHECK: [[BOUNDSCHECK_NOTNULL89]]: -// CHECK-NEXT: [[FAM90:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY91:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM90]], i64 0, i64 0 -// CHECK-NEXT: [[HDR92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 -// CHECK-NEXT: [[LEN93:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR92]], i32 0, i32 1 -// CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[LEN93]], align 8 -// CHECK-NEXT: [[IDX_EXT94:%.*]] = sext i32 [[TMP25]] to i64 -// CHECK-NEXT: [[ADD_PTR95:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY91]], i64 [[IDX_EXT94]] -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR95]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP23]], i32 0, i32 0 +// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR83]], ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[HDR88:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP24]], i32 0, i32 0 +// CHECK-NEXT: [[LEN89:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR88]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[LEN89]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = icmp ne ptr [[TMP25]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP26]], label %[[BOUNDSCHECK_NOTNULL91:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL91]]: +// CHECK-NEXT: [[FAM92:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP25]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY93:%.*]] = getelementptr inbounds [0 x i32], ptr [[FAM92]], i64 0, i64 0 +// CHECK-NEXT: [[HDR94:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP25]], i32 0, i32 0 +// CHECK-NEXT: [[LEN95:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR94]], i32 0, i32 1 +// CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[LEN95]], align 8 +// CHECK-NEXT: [[IDX_EXT96:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK-NEXT: [[ADD_PTR97:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY93]], i64 [[IDX_EXT96]] +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR97]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP30]], align 8 // CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] // CHECK: [[BOUNDSCHECK_NULL]]: -// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP29]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP30]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP33]], align 8 // CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] // CHECK: [[BOUNDSCHECK_CONT]]: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR96:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR97:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR96]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB99:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR98]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB101:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR100]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[WIDE_PTR_PTR97]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP32]], label %[[BOUNDSCHECK_NOTNULL102:.*]], label %[[CONT106:.*]], !annotation [[META4]] -// CHECK: [[BOUNDSCHECK_NOTNULL102]]: -// CHECK-NEXT: [[TMP33:%.*]] = icmp ult ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_UB99]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT104:.*]], label %[[TRAP103:.*]], !prof [[PROF3]], !annotation [[META6]] -// CHECK: [[TRAP103]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META6]] -// CHECK-NEXT: unreachable, !annotation [[META6]] -// CHECK: [[CONT104]]: -// CHECK-NEXT: [[TMP34:%.*]] = icmp uge ptr [[WIDE_PTR_PTR97]], [[WIDE_PTR_LB101]], !annotation [[META7]] -// CHECK-NEXT: br i1 [[TMP34]], label %[[CONT106]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR98:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR99:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR98]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB101:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR100]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP90]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB103:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR102]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = icmp ne ptr [[WIDE_PTR_PTR99]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP34]], label %[[BOUNDSCHECK_NOTNULL104:.*]], label %[[CONT110:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL104]]: +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR99]], i64 1, !annotation [[META12]] +// CHECK-NEXT: [[TMP36:%.*]] = icmp ule ptr [[TMP35]], [[WIDE_PTR_UB101]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP36]], label %[[CONT106:.*]], label %[[TRAP105:.*]], !prof [[PROF3]], !annotation [[META12]] // CHECK: [[TRAP105]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT106]]: +// CHECK-NEXT: [[TMP37:%.*]] = icmp ule ptr [[WIDE_PTR_PTR99]], [[TMP35]], !annotation [[META12]] +// CHECK-NEXT: br i1 [[TMP37]], label %[[CONT108:.*]], label %[[TRAP107:.*]], !prof [[PROF3]], !annotation [[META12]] +// CHECK: [[TRAP107]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META12]] +// CHECK-NEXT: unreachable, !annotation [[META12]] +// CHECK: [[CONT108]]: +// CHECK-NEXT: [[TMP38:%.*]] = icmp uge ptr [[WIDE_PTR_PTR99]], [[WIDE_PTR_LB103]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP38]], label %[[CONT110]], label %[[TRAP109:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP109]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], !annotation [[META7]] // CHECK-NEXT: unreachable, !annotation [[META7]] -// CHECK: [[CONT106]]: -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR97]] +// CHECK: [[CONT110]]: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR99]] // struct Outer *foo2(int len) { int * p2 = baz(len); @@ -559,4 +586,5 @@ struct Outer *foo2(int len) { // CHECK: [[META9]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-le-upper-bound"} // CHECK: [[META10]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-ge-lower-bound"} // CHECK: [[META11]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[META12]] = !{!"bounds-safety-check-ptr-le-upper-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O2.c b/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O2.c index c33dced3d3f09..989ddb937de81 100644 --- a/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O2.c +++ b/clang/test/BoundsSafety/CodeGen/flexible-array-member-shared-decls-O2.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 - // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s #include @@ -35,12 +34,12 @@ int * __counted_by(len) baz(int len); // CHECK-NEXT: unreachable, !annotation [[META5]] // CHECK: [[CONT]]: // CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[CALL1]], null, !annotation [[META6:![0-9]+]] -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT69:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT70:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] // CHECK: [[FLEX_BASE_NONNULL]]: // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[CALL1]], i64 16 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[CALL1]], [[TMP1]], !annotation [[META7:![0-9]+]] -// CHECK-NEXT: [[DOTNOT106:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8:![0-9]+]] -// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT106]], !annotation [[META8]] +// CHECK-NEXT: [[DOTNOT110:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT110]], !annotation [[META8]] // CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP]], label %[[CONT60:.*]], !prof [[PROF9:![0-9]+]], !annotation [[META7]] // CHECK: [[CONT60]]: // CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[ADD_PTR3]] to i64, !annotation [[META10:![0-9]+]] @@ -48,13 +47,11 @@ int * __counted_by(len) baz(int len); // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META10]] // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[FLEX_AVAIL_COUNT]], 2, !annotation [[META10]] // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation [[META10]] -// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[CALL1]], [[ADD_PTR3]], !annotation [[META8]] -// CHECK-NEXT: [[OR_COND108:%.*]] = select i1 [[FLEX_COUNT_CHECK_NOT]], i1 [[TMP2]], i1 false, !annotation [[META6]] -// CHECK-NEXT: br i1 [[OR_COND108]], label %[[CONT69]], label %[[TRAP]], !prof [[PROF11:![0-9]+]], !annotation [[META10]] -// CHECK: [[CONT69]]: -// CHECK-NEXT: [[LEN70:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 -// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN70]], align 8, !tbaa [[TBAA12:![0-9]+]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT_NOT:%.*]] = icmp ult i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK_NOT_NOT]], label %[[TRAP]], label %[[CONT70]], !prof [[PROF11:![0-9]+]], !annotation [[META10]] +// CHECK: [[CONT70]]: +// CHECK-NEXT: [[LEN71:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN71]], align 8, !tbaa [[TBAA12:![0-9]+]] // CHECK-NEXT: store ptr [[CALL]], ptr [[CALL1]], align 8, !tbaa [[TBAA19:![0-9]+]] // CHECK-NEXT: ret ptr [[CALL1]] // @@ -84,12 +81,12 @@ struct Outer *foo(int len) { // CHECK-NEXT: unreachable, !annotation [[META5]] // CHECK: [[CONT]]: // CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[CALL1]], null, !annotation [[META6]] -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT69:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label %[[CONT70:.*]], label %[[FLEX_BASE_NONNULL:.*]], !annotation [[META6]] // CHECK: [[FLEX_BASE_NONNULL]]: // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[CALL1]], i64 16 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[CALL1]], [[TMP1]], !annotation [[META7]] -// CHECK-NEXT: [[DOTNOT106:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8]] -// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT106]], !annotation [[META8]] +// CHECK-NEXT: [[DOTNOT110:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR3]], !annotation [[META8]] +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT110]], !annotation [[META8]] // CHECK-NEXT: br i1 [[OR_COND]], label %[[TRAP]], label %[[CONT60:.*]], !prof [[PROF9]], !annotation [[META7]] // CHECK: [[CONT60]]: // CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[ADD_PTR3]] to i64, !annotation [[META10]] @@ -97,14 +94,12 @@ struct Outer *foo(int len) { // CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META10]] // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[FLEX_AVAIL_COUNT]], 2, !annotation [[META10]] // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation [[META10]] -// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[CALL1]], [[ADD_PTR3]], !annotation [[META8]] -// CHECK-NEXT: [[OR_COND108:%.*]] = select i1 [[FLEX_COUNT_CHECK_NOT]], i1 [[TMP2]], i1 false, !annotation [[META6]] -// CHECK-NEXT: br i1 [[OR_COND108]], label %[[CONT69]], label %[[TRAP]], !prof [[PROF11]], !annotation [[META10]] -// CHECK: [[CONT69]]: +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT_NOT:%.*]] = icmp ult i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK_NOT_NOT]], label %[[TRAP]], label %[[CONT70]], !prof [[PROF11]], !annotation [[META10]] +// CHECK: [[CONT70]]: // CHECK-NEXT: store ptr [[CALL]], ptr [[CALL1]], align 8, !tbaa [[TBAA19]] -// CHECK-NEXT: [[LEN78:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 -// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN78]], align 8, !tbaa [[TBAA12]] +// CHECK-NEXT: [[LEN79:%.*]] = getelementptr inbounds nuw i8, ptr [[CALL1]], i64 8 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN79]], align 8, !tbaa [[TBAA12]] // CHECK-NEXT: ret ptr [[CALL1]] // struct Outer *foo2(int len) { @@ -124,7 +119,7 @@ struct Outer *foo2(int len) { // CHECK: [[META8]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} // CHECK: [[PROF9]] = !{!"branch_weights", i32 12286, i32 -12288} // CHECK: [[META10]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} -// CHECK: [[PROF11]] = !{!"branch_weights", i32 -8193, i32 8190} +// CHECK: [[PROF11]] = !{!"branch_weights", i32 16381, i32 -16384} // CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META18:![0-9]+]], i64 8} // CHECK: [[META13]] = !{!"Inner", [[META14:![0-9]+]], i64 0, [[META18]], i64 8} // CHECK: [[META14]] = !{!"p1 int", [[META15:![0-9]+]], i64 0} diff --git a/clang/test/BoundsSafety/CodeGen/incomplete-array-counted.c b/clang/test/BoundsSafety/CodeGen/incomplete-array-counted.c index 4eb3bf102e5df..ee4b297e901cd 100644 --- a/clang/test/BoundsSafety/CodeGen/incomplete-array-counted.c +++ b/clang/test/BoundsSafety/CodeGen/incomplete-array-counted.c @@ -1,17 +1,18 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -o /dev/null -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o /dev/null +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --version 5 +// FIXME: Have to use `arm64e-apple-iphoneos` instead of `arm64e-apple-ios` to get `update_cc_test_checks.py` to add IR to this test +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-iphoneos -fbounds-safety -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o /dev/null #include extern unsigned externArray[__counted_by(10)]; void bar(const unsigned *pointer); -// CHECK-LABEL: @foo( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @foo( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr @externArray, ptr [[TMP0]], align 8 @@ -26,25 +27,33 @@ void bar(const unsigned *pointer); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br i1 [[TMP3]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT4:.*]], {{!annotation ![0-9]+}} +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: -// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap1: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT4]], label %[[TRAP3:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP3]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont2: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT4]]: // CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // void foo(void){ bar(externArray); } - - +//. +// CHECK: [[PROF4]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/incomplete-array.c b/clang/test/BoundsSafety/CodeGen/incomplete-array.c index d5a31c51d100b..262d2541a45b1 100644 --- a/clang/test/BoundsSafety/CodeGen/incomplete-array.c +++ b/clang/test/BoundsSafety/CodeGen/incomplete-array.c @@ -1,19 +1,20 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm -Werror -verify=werr %s -o /dev/null -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s -// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -emit-llvm %s -verify=default -o /dev/null -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -Werror -verify=werr %s -o /dev/null -// RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s -// RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -verify=default -o /dev/null +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --version 5 +// FIXME: Have to use `arm64e-apple-iphoneos` instead of `arm64e-apple-ios` to get `update_cc_test_checks.py` to add IR to this test +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -emit-llvm -Werror -verify=werr %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-iphoneos -fbounds-safety -emit-llvm %s -verify=default -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -Werror -verify=werr %s -o /dev/null +// RUN: %clang_cc1 -O0 -triple arm64e-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -Wno-bounds-safety-incomplete-array -verify=wno -o - | FileCheck %s +// RUN: %clang_cc1 -O2 -triple arm64e-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -verify=default -o /dev/null // wno-no-diagnostics extern unsigned externArray[]; void bar(const unsigned *pointer); -// CHECK-LABEL: @foo( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @foo( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr @externArray, ptr [[TMP0]], align 8 @@ -28,20 +29,27 @@ void bar(const unsigned *pointer); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br i1 [[TMP3]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT4:.*]], {{!annotation ![0-9]+}} +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont: -// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap1: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT4]], label %[[TRAP3:.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP3]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont2: +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT4]]: // CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -51,3 +59,6 @@ void foo(void){ } +//. +// CHECK: [[PROF4]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/CodeGen/index-enum-signed.c b/clang/test/BoundsSafety/CodeGen/index-enum-signed.c index 525215dce2688..1c26e16f63521 100644 --- a/clang/test/BoundsSafety/CodeGen/index-enum-signed.c +++ b/clang/test/BoundsSafety/CodeGen/index-enum-signed.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -fshort-enums -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -fshort-enums -emit-llvm %s -o - | FileCheck %s @@ -25,25 +24,32 @@ enum bar { // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[B]], align 1 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i8 [[TMP1]] to i64 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[TMP2]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK-NEXT: ret i32 [[TMP5]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP6]] // int baz(int i) { int *__bidi_indexable ptr; diff --git a/clang/test/BoundsSafety/CodeGen/index-enum-unsigned.c b/clang/test/BoundsSafety/CodeGen/index-enum-unsigned.c index ff287ee7f770f..b8e9b083c33bc 100644 --- a/clang/test/BoundsSafety/CodeGen/index-enum-unsigned.c +++ b/clang/test/BoundsSafety/CodeGen/index-enum-unsigned.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -fshort-enums -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -fshort-enums -emit-llvm %s -o - | FileCheck %s @@ -25,25 +24,32 @@ enum bar { // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[B]], align 1 // CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[TMP1]] to i64 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[TMP2]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK-NEXT: ret i32 [[TMP5]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP6]] // int baz(int i) { int *__bidi_indexable ptr; diff --git a/clang/test/BoundsSafety/CodeGen/index-signed.c b/clang/test/BoundsSafety/CodeGen/index-signed.c index c880484be0d84..02f54ad0976b0 100644 --- a/clang/test/BoundsSafety/CodeGen/index-signed.c +++ b/clang/test/BoundsSafety/CodeGen/index-signed.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -18,24 +17,31 @@ // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[SIGNED_IDX]], align 2 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i16 [[TMP0]] to i64 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[TMP1]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 // CHECK-NEXT: ret i32 0 // int main() { diff --git a/clang/test/BoundsSafety/CodeGen/index-unsigned.c b/clang/test/BoundsSafety/CodeGen/index-unsigned.c index 59280312f55a8..43381adb11258 100644 --- a/clang/test/BoundsSafety/CodeGen/index-unsigned.c +++ b/clang/test/BoundsSafety/CodeGen/index-unsigned.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -17,24 +16,31 @@ // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[UNSIGNED_IDX]], align 2 // CHECK-NEXT: [[IDXPROM:%.*]] = zext i16 [[TMP0]] to i64 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[TMP1]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP1]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 // CHECK-NEXT: ret i32 0 // int main() { diff --git a/clang/test/BoundsSafety/CodeGen/indexable-arithmetic.c b/clang/test/BoundsSafety/CodeGen/indexable-arithmetic.c index cf5b8cb7efc65..27b19198d1e81 100644 --- a/clang/test/BoundsSafety/CodeGen/indexable-arithmetic.c +++ b/clang/test/BoundsSafety/CodeGen/indexable-arithmetic.c @@ -30,20 +30,27 @@ // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP9:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP10:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[TMP10]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP11:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP10]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: ret ptr [[WIDE_PTR_PTR]] // int *foo(int *__bidi_indexable ptr) { diff --git a/clang/test/BoundsSafety/CodeGen/large-array-subscript-x86_64.c b/clang/test/BoundsSafety/CodeGen/large-array-subscript-x86_64.c index b5fea2b6a9aba..73d783a440444 100644 --- a/clang/test/BoundsSafety/CodeGen/large-array-subscript-x86_64.c +++ b/clang/test/BoundsSafety/CodeGen/large-array-subscript-x86_64.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // XXX: Previously, rdar://132269322 was caused by incorrectly emitting 'align 16' here @@ -11,20 +10,27 @@ // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [80 x float], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[ARRAYDECAY]], i64 80 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr float, ptr [[ARRAYDECAY]], i64 19 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], !annotation [[META2:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[ARRAYIDX]], i64 1, !annotation [[META2:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] // CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // CHECK: [[CONT]]: -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARRAYDECAY]], !annotation [[META4:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP1]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP2]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARRAYDECAY]], !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP3]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP3]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META4]] // CHECK-NEXT: unreachable, !annotation [[META4]] -// CHECK: [[CONT2]]: -// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[ARRAYIDX]], align 4 -// CHECK-NEXT: ret float [[TMP2]] +// CHECK: [[CONT4]]: +// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret float [[TMP4]] // float large_array_subscript(void) { float arr[80] = {0}; @@ -59,29 +65,36 @@ float large_array_subscript(void) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr float, ptr [[ARRAYIDX]], i64 1, !annotation [[META2]] +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] // CHECK: [[CONT]]: -// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP6]], !annotation [[META2]] +// CHECK-NEXT: br i1 [[TMP8]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META2]] // CHECK: [[TRAP1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] +// CHECK-NEXT: unreachable, !annotation [[META2]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP3]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META4]] // CHECK-NEXT: unreachable, !annotation [[META4]] -// CHECK: [[CONT2]]: -// CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[ARRAYIDX]], align 4 -// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 -// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP9]]) -// CHECK-NEXT: ret float [[TMP8]] +// CHECK: [[CONT4]]: +// CHECK-NEXT: [[TMP10:%.*]] = load float, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP11]]) +// CHECK-NEXT: ret float [[TMP10]] // float vla_subscript(int size) { float arr[size]; return arr[19]; } //. -// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-le-upper-bound"} // CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} // CHECK: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/member-expr.c b/clang/test/BoundsSafety/CodeGen/member-expr.c index c2dd383489334..04322d26bd496 100644 --- a/clang/test/BoundsSafety/CodeGen/member-expr.c +++ b/clang/test/BoundsSafety/CodeGen/member-expr.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s #include @@ -35,20 +34,27 @@ void escape_ptr_bidi(int *__bidi_indexable p); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -77,20 +83,27 @@ void foo_single_bar_single(struct foo *__single f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -120,20 +133,27 @@ void foo_single_baz_single(struct foo *__single f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -177,20 +197,27 @@ void foo_single_frob_single(struct foo *__single f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP14:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP14]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -309,48 +336,62 @@ void foo_single_frob4_bidi(struct foo *__single f) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap2: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont3: -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap10: +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap4: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont11: -// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: cont5: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT17:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[TMP10]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: -// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[WIDE_PTR_PTR7]], [[TMP10]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap14: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont15: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT17]], label [[TRAP16:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap16: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont17: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR7]]) // CHECK-NEXT: ret void // void foo_bidi_bar_single(struct foo *__bidi_indexable f) { @@ -368,48 +409,62 @@ void foo_bidi_bar_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap2: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont3: -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-NEXT: [[TMP7:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP8:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap10: +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap4: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont11: -// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK: cont5: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT17:%.*]], {{!annotation ![0-9]+}} +// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[TMP10]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: -// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) +// CHECK-NEXT: [[TMP12:%.*]] = icmp ule ptr [[WIDE_PTR_PTR7]], [[TMP10]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap14: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont15: +// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT17]], label [[TRAP16:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap16: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont17: +// CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR7]]) // CHECK-NEXT: ret void // void foo_bidi_baz_single(struct foo *__bidi_indexable f) { @@ -429,13 +484,13 @@ void foo_bidi_baz_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap2: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -456,20 +511,27 @@ void foo_bidi_baz_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT15:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: -// CHECK-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP10]], label [[CONT15]], label [[TRAP14:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap14: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont15: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) // CHECK-NEXT: ret void // @@ -491,13 +553,13 @@ void foo_bidi_frob_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT3:%.*]], label [[TRAP2:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap2: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -531,20 +593,27 @@ void foo_bidi_frob_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 // CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT13:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT15:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP16:%.*]] = icmp ult ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP16]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP17:%.*]] = icmp ule ptr [[TMP16]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP17]], label [[CONT11:%.*]], label [[TRAP10:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap10: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont11: -// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP17]], label [[CONT13]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP18:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP18]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap12: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont13: +// CHECK-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP19]], label [[CONT15]], label [[TRAP14:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap14: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont15: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR5]]) // CHECK-NEXT: ret void // @@ -563,26 +632,33 @@ void foo_bidi_frob4_single(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP8]], align 8 // CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) // CHECK-NEXT: ret void // @@ -601,26 +677,33 @@ void foo_bidi_bar_bidi(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[WIDE_PTR_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP8]], align 8 // CHECK-NEXT: call void @escape_ptr_bidi(ptr noundef byval(%"__bounds_safety::wide_ptr.bidi_indexable") align 8 [[AGG_TMP]]) // CHECK-NEXT: ret void // @@ -641,13 +724,13 @@ void foo_bidi_baz_bidi(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -682,13 +765,13 @@ void foo_bidi_frob_bidi(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -741,20 +824,27 @@ void foo_bidi_frob4_bidi(struct foo *__bidi_indexable f) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP6]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -782,20 +872,27 @@ void foo_dot_bar_single(void) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP6:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP6]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP9:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -824,20 +921,27 @@ void foo_dot_baz_single(void) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP4:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP5:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // @@ -880,20 +984,27 @@ void foo_dot_frob_single(void) { // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP12:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP12]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT2]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont2: +// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont4: // CHECK-NEXT: call void @escape_ptr_single(ptr noundef [[WIDE_PTR_PTR]]) // CHECK-NEXT: ret void // diff --git a/clang/test/BoundsSafety/CodeGen/multiple-dependees.c b/clang/test/BoundsSafety/CodeGen/multiple-dependees.c index 7daae4a7ffbdf..ef9527a1c7a80 100644 --- a/clang/test/BoundsSafety/CodeGen/multiple-dependees.c +++ b/clang/test/BoundsSafety/CodeGen/multiple-dependees.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 %s -O0 -fbounds-safety -triple x86_64 -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -triple x86_64 -emit-llvm -o - | FileCheck %s @@ -94,7 +93,7 @@ struct T { // CHECK-NEXT: br label [[LAND_END29]], {{!annotation ![0-9]+}} // CHECK: land.end29: // CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP3]], [[LAND_END]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -134,25 +133,32 @@ struct T { // CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 // CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[IDX_ADDR]], align 4 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP11]] to i64 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR47]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR47]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[TMP12]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT53:%.*]], label [[TRAP52:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB49]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT53:%.*]], label [[TRAP52:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap52: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont53: -// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[TMP12]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT55:%.*]], label [[TRAP54:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT55:%.*]], label [[TRAP54:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} // CHECK: trap54: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont55: -// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP12]], align 4 -// CHECK-NEXT: ret i32 [[TMP15]] +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB51]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT57:%.*]], label [[TRAP56:%.*]], !prof [[PROF4]], {{!annotation ![0-9]+}} +// CHECK: trap56: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont57: +// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP16]] // int Foo(int idx) { int arr[16] = { 0 }; diff --git a/clang/test/BoundsSafety/CodeGen/nested-struct-member-count-O2.c b/clang/test/BoundsSafety/CodeGen/nested-struct-member-count-O2.c index 23f3e7a6dadfa..91ca1b9027757 100644 --- a/clang/test/BoundsSafety/CodeGen/nested-struct-member-count-O2.c +++ b/clang/test/BoundsSafety/CodeGen/nested-struct-member-count-O2.c @@ -1,5 +1,4 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --version 4 - +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -20,20 +19,20 @@ struct Outer { // CHECK-NEXT: entry: // CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 8 // CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4, !tbaa {{![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[FAM]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[FAM]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[ADD_PTR]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[FAM]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP1]], !annotation {{![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT8:%.*]], label [[TRAP:%.*]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[ADD_PTR]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[FAM]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP1]], !annotation [[META8]] +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT8:%.*]], label [[TRAP:%.*]], !prof [[PROF9:![0-9]+]], !annotation [[META7]] // CHECK: trap: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], !annotation {{![0-9]+}} -// CHECK-NEXT: unreachable, !annotation {{![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], !annotation [[META10:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META10]] // CHECK: cont8: -// CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa {{![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA11:![0-9]+]] // CHECK-NEXT: ret i8 [[TMP3]] // char access(struct Outer *bar, int index) { @@ -45,36 +44,34 @@ char access(struct Outer *bar, int index) { // CHECK-LABEL: define dso_local noundef nonnull ptr @assign( // CHECK-SAME: ptr noundef readonly captures(none) [[BAR:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[BAR]], align 8, !nonnull {{![0-9]+}}, !noundef {{![0-9]+}} +// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[BAR]], align 8, !nonnull [[META12:![0-9]+]], !noundef [[META12]] // CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 8 // CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 8 -// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[TMP0]], !annotation {{![0-9]+}} -// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[TMP0]], !annotation [[META13:![0-9]+]] +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof [[PROF14:![0-9]+]], !annotation [[META13]] // CHECK: trap: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], !annotation {{![0-9]+}} -// CHECK-NEXT: unreachable, !annotation {{![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], !annotation [[META15:![0-9]+]] +// CHECK-NEXT: unreachable, !annotation [[META15]] // CHECK: cont: // CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 16 -// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX]], align 8, !tbaa {{![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[AGG_TEMP1_SROA_3_0_COPYLOAD]], [[AGG_TEMP1_SROA_0_0_COPYLOAD]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 false, !annotation {{![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT18:%.*]], label [[TRAP]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} +// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX]], align 8, !tbaa [[TBAA16:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation [[META7]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[AGG_TEMP1_SROA_3_0_COPYLOAD]], [[AGG_TEMP1_SROA_0_0_COPYLOAD]], !annotation [[META8]] +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 false, !annotation [[META8]] +// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT18:%.*]], label [[TRAP]], !prof [[PROF9]], !annotation [[META7]] // CHECK: cont18: -// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation {{![0-9]+}} -// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_2_0_COPYLOAD]] to i64, !annotation {{![0-9]+}} -// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation {{![0-9]+}} -// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation {{![0-9]+}} -// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT]], [[FLEX_COUNT_INTPTR]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[OR_COND49:%.*]] = select i1 [[FLEX_COUNT_MINUS]], i1 [[FLEX_COUNT_CHECK]], i1 false, !annotation {{![0-9]+}} -// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}} -// CHECK-NEXT: [[OR_COND60:%.*]] = select i1 [[OR_COND49]], i1 [[TMP3]], i1 false, !annotation {{![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND60]], label [[BOUNDSCHECK_CONT:%.*]], label [[TRAP]], !prof {{![0-9]+}}, !annotation {{![0-9]+}} -// CHECK: boundscheck.cont: -// CHECK-NEXT: [[LEN31:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 4 -// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN31]], align 4, !tbaa {{![0-9]+}} +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META18:![0-9]+]] +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_2_0_COPYLOAD]] to i64, !annotation [[META19:![0-9]+]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META19]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META19]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[LEN]] to i64, !annotation [[META19]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp uge i64 [[FLEX_AVAIL_COUNT]], [[FLEX_COUNT_INTPTR]], !annotation [[META19]] +// CHECK-NEXT: [[OR_COND51:%.*]] = select i1 [[FLEX_COUNT_MINUS]], i1 [[FLEX_COUNT_CHECK]], i1 false, !annotation [[META19]] +// CHECK-NEXT: br i1 [[OR_COND51]], label [[BOUNDSCHECK_NOTNULL45:%.*]], label [[TRAP]], !prof [[PROF20:![0-9]+]], !annotation [[META18]] +// CHECK: boundscheck.notnull45: +// CHECK-NEXT: [[LEN32:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 4 +// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN32]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: ret ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]] // struct Outer * assign(void * __bidi_indexable bar, int len) { @@ -82,3 +79,24 @@ struct Outer * assign(void * __bidi_indexable bar, int len) { s->hdr.len = len; return s; } +//. +// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META4:![0-9]+]], i64 4} +// CHECK: [[META3]] = !{!"Inner", [[META4]], i64 0, [[META4]], i64 4} +// CHECK: [[META4]] = !{!"int", [[META5:![0-9]+]], i64 0} +// CHECK: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[META7]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK: [[META8]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[PROF9]] = !{!"branch_weights", i32 -8192, i32 8191} +// CHECK: [[META10]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[TBAA11]] = !{[[META5]], [[META5]], i64 0} +// CHECK: [[META12]] = !{} +// CHECK: [[META13]] = !{!"bounds-safety-check-one-past-end-overflow"} +// CHECK: [[PROF14]] = !{!"branch_weights", i32 1, i32 1048575} +// CHECK: [[META15]] = !{!"bounds-safety-check-one-past-end-overflow", !"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-check-count-negative", !"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[TBAA16]] = !{[[META17:![0-9]+]], [[META17]], i64 0} +// CHECK: [[META17]] = !{!"any pointer", [[META5]], i64 0} +// CHECK: [[META18]] = !{!"bounds-safety-check-count-negative"} +// CHECK: [[META19]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[PROF20]] = !{!"branch_weights", i32 -16384, i32 16381} +//. diff --git a/clang/test/BoundsSafety/CodeGen/nested-struct-member-count.c b/clang/test/BoundsSafety/CodeGen/nested-struct-member-count.c index b6be10a157cc2..580a9ac88259e 100644 --- a/clang/test/BoundsSafety/CodeGen/nested-struct-member-count.c +++ b/clang/test/BoundsSafety/CodeGen/nested-struct-member-count.c @@ -1,6 +1,5 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -18,7 +17,7 @@ struct Outer { // CHECK-LABEL: define dso_local i8 @access( // CHECK-SAME: ptr noundef [[BAR:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[BAR_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -57,25 +56,25 @@ struct Outer { // CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 // CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP9]] to i64 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[WIDE_PTR_PTR5]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[WIDE_PTR_PTR5]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = icmp ult ptr [[TMP10]], [[WIDE_PTR_UB7]], !annotation [[META2:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP11]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: +// CHECK-NEXT: [[TMP10:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB7]], !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: -// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[TMP10]], [[WIDE_PTR_LB]], !annotation [[META3:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !annotation [[META3]] -// CHECK: trap8: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] -// CHECK-NEXT: unreachable, !annotation [[META3]] -// CHECK: cont9: -// CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP10]], align 1 -// CHECK-NEXT: ret i8 [[TMP13]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP11:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP11]], label %[[CONT9:.*]], label %[[TRAP8:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP8]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT9]]: +// CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +// CHECK-NEXT: ret i8 [[TMP12]] // char access(struct Outer *bar, int index) { return bar->fam[index]; @@ -84,7 +83,7 @@ char access(struct Outer *bar, int index) { // CHECK-LABEL: define dso_local ptr @assign( // CHECK-SAME: ptr noundef [[BAR:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[BAR_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[S:%.*]] = alloca ptr, align 8 @@ -93,7 +92,7 @@ char access(struct Outer *bar, int index) { // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: store ptr [[BAR]], ptr [[BAR_INDIRECT_ADDR]], align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[BAR]], i64 24, i1 false) @@ -117,16 +116,16 @@ char access(struct Outer *bar, int index) { // CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP3]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, !annotation [[META4:![0-9]+]] -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label [[FLEX_BASE_NONNULL:%.*]], label [[CONT28:%.*]], !annotation [[META4]] -// CHECK: flex.base.nonnull: +// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK:%.*]] = icmp ne ptr [[WIDE_PTR_PTR5]], null, !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK]], label %[[FLEX_BASE_NONNULL:.*]], label %[[CONT28:.*]], !annotation [[META5]] +// CHECK: [[FLEX_BASE_NONNULL]]: // CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_OUTER:%.*]], ptr [[WIDE_PTR_PTR5]], i64 1 -// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP4]], !annotation [[META5:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META5]] -// CHECK-NEXT: unreachable, !annotation [[META5]] -// CHECK: cont: +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR5]], [[TMP4]], !annotation [[META6:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP5]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], !annotation [[META6]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP10]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR12:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR11]], align 8 @@ -136,47 +135,47 @@ char access(struct Outer *bar, int index) { // CHECK-NEXT: [[WIDE_PTR_LB16:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR15]], align 8 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR12]], i64 1 // CHECK-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB14]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP7]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !annotation [[META2]] -// CHECK: trap17: +// CHECK-NEXT: br i1 [[TMP7]], label %[[CONT18:.*]], label %[[TRAP17:.*]], !prof [[PROF3]], !annotation [[META2]] +// CHECK: [[TRAP17]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] // CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont18: -// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP8]], label [[CONT20:%.*]], label [[TRAP19:%.*]], !annotation [[META3]] -// CHECK: trap19: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] -// CHECK-NEXT: unreachable, !annotation [[META3]] -// CHECK: cont20: +// CHECK: [[CONT18]]: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ule ptr [[WIDE_PTR_LB16]], [[WIDE_PTR_PTR12]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP8]], label %[[CONT20:.*]], label %[[TRAP19:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP19]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT20]]: // CHECK-NEXT: [[FAM:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR12]], i32 0, i32 1 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM]], i64 0, i64 0 -// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP3]], !annotation [[META6:![0-9]+]] -// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !annotation [[META6]] -// CHECK: trap21: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META6]] -// CHECK-NEXT: unreachable, !annotation [[META6]] -// CHECK: cont22: -// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB7]], !annotation [[META7:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !annotation [[META7]] -// CHECK: trap23: +// CHECK-NEXT: [[FLEX_COUNT_MINUS:%.*]] = icmp sle i32 0, [[TMP3]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_MINUS]], label %[[CONT22:.*]], label %[[TRAP21:.*]], !prof [[PROF3]], !annotation [[META7]] +// CHECK: [[TRAP21]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META7]] // CHECK-NEXT: unreachable, !annotation [[META7]] -// CHECK: cont24: -// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], !annotation [[META8:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !annotation [[META8]] -// CHECK: trap25: +// CHECK: [[CONT22]]: +// CHECK-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYDECAY]], [[WIDE_PTR_UB7]], !annotation [[META8:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT24:.*]], label %[[TRAP23:.*]], !prof [[PROF3]], !annotation [[META8]] +// CHECK: [[TRAP23]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META8]] // CHECK-NEXT: unreachable, !annotation [[META8]] -// CHECK: cont26: -// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, !annotation [[META9:![0-9]+]] -// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, !annotation [[META9]] -// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META9]] -// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP3]] to i64, !annotation [[META9]] -// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT]], !annotation [[META9]] -// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label [[CONT28]], label [[TRAP27:%.*]], !annotation [[META9]] -// CHECK: trap27: +// CHECK: [[CONT24]]: +// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR5]], [[WIDE_PTR_LB9]], !annotation [[META9:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT26:.*]], label %[[TRAP25:.*]], !prof [[PROF3]], !annotation [[META9]] +// CHECK: [[TRAP25]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META9]] // CHECK-NEXT: unreachable, !annotation [[META9]] -// CHECK: cont28: +// CHECK: [[CONT26]]: +// CHECK-NEXT: [[UPPER_INTPTR:%.*]] = ptrtoint ptr [[WIDE_PTR_UB7]] to i64, !annotation [[META10:![0-9]+]] +// CHECK-NEXT: [[FAM_INTPTR:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_AVAIL_COUNT:%.*]] = sub nuw i64 [[UPPER_INTPTR]], [[FAM_INTPTR]], !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext i32 [[TMP3]] to i64, !annotation [[META10]] +// CHECK-NEXT: [[FLEX_COUNT_CHECK:%.*]] = icmp ule i64 [[FLEX_COUNT_INTPTR]], [[FLEX_AVAIL_COUNT]], !annotation [[META10]] +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK]], label %[[CONT28]], label %[[TRAP27:.*]], !prof [[PROF3]], !annotation [[META10]] +// CHECK: [[TRAP27]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META10]] +// CHECK-NEXT: unreachable, !annotation [[META10]] +// CHECK: [[CONT28]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8 @@ -184,75 +183,89 @@ char access(struct Outer *bar, int index) { // CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT38:%.*]], !annotation [[META4]] -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_UB32]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT36:%.*]], label [[TRAP35:%.*]], !annotation [[META2]] -// CHECK: trap35: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont36: -// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT38]], label [[TRAP37:%.*]], !annotation [[META3]] -// CHECK: trap37: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] -// CHECK-NEXT: unreachable, !annotation [[META3]] -// CHECK: cont38: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP11]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT40:.*]], !annotation [[META5]] +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR30]], i64 1, !annotation [[META11:![0-9]+]] +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB32]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[TMP13]], label %[[CONT36:.*]], label %[[TRAP35:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP35]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT36]]: +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR30]], [[TMP12]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT38:.*]], label %[[TRAP37:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP37]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT38]]: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_LB34]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT40]], label %[[TRAP39:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP39]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT40]]: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR30]], ptr [[S]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[S]], align 8 -// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP14]], i32 0, i32 0 -// CHECK-NEXT: [[LEN39:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 -// CHECK-NEXT: store i32 [[TMP3]], ptr [[LEN39]], align 4 -// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[S]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP15]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL41:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META4]] -// CHECK: boundscheck.notnull41: -// CHECK-NEXT: [[FAM42:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP15]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY43:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM42]], i64 0, i64 0 -// CHECK-NEXT: [[HDR44:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP15]], i32 0, i32 0 -// CHECK-NEXT: [[LEN45:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR44]], i32 0, i32 1 -// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[LEN45]], align 4 -// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP17]] to i64 -// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY43]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP19]], align 8 -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP20]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] -// CHECK: boundscheck.null: -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[S]], align 8 +// CHECK-NEXT: [[HDR:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP16]], i32 0, i32 0 +// CHECK-NEXT: [[LEN41:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER:%.*]], ptr [[HDR]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[LEN41]], align 4 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[S]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = icmp ne ptr [[TMP17]], null, !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP18]], label %[[BOUNDSCHECK_NOTNULL43:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META5]] +// CHECK: [[BOUNDSCHECK_NOTNULL43]]: +// CHECK-NEXT: [[FAM44:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP17]], i32 0, i32 1 +// CHECK-NEXT: [[ARRAYDECAY45:%.*]] = getelementptr inbounds [0 x i8], ptr [[FAM44]], i64 0, i64 0 +// CHECK-NEXT: [[HDR46:%.*]] = getelementptr inbounds nuw [[STRUCT_OUTER]], ptr [[TMP17]], i32 0, i32 0 +// CHECK-NEXT: [[LEN47:%.*]] = getelementptr inbounds nuw [[STRUCT_INNER]], ptr [[HDR46]], i32 0, i32 1 +// CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[LEN47]], align 4 +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP19]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAYDECAY45]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP22]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP23]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] -// CHECK: boundscheck.cont: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = icmp ne ptr [[WIDE_PTR_PTR47]], null, !annotation [[META4]] -// CHECK-NEXT: br i1 [[TMP24]], label [[BOUNDSCHECK_NOTNULL52:%.*]], label [[CONT56:%.*]], !annotation [[META4]] -// CHECK: boundscheck.notnull52: -// CHECK-NEXT: [[TMP25:%.*]] = icmp ult ptr [[WIDE_PTR_PTR47]], [[WIDE_PTR_UB49]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP25]], label [[CONT54:%.*]], label [[TRAP53:%.*]], !annotation [[META2]] -// CHECK: trap53: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont54: -// CHECK-NEXT: [[TMP26:%.*]] = icmp uge ptr [[WIDE_PTR_PTR47]], [[WIDE_PTR_LB51]], !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP26]], label [[CONT56]], label [[TRAP55:%.*]], !annotation [[META3]] -// CHECK: trap55: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] -// CHECK-NEXT: unreachable, !annotation [[META3]] -// CHECK: cont56: -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR47]] +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP25]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR49:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR48]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB51:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR50]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB53:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR52]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = icmp ne ptr [[WIDE_PTR_PTR49]], null, !annotation [[META5]] +// CHECK-NEXT: br i1 [[TMP26]], label %[[BOUNDSCHECK_NOTNULL54:.*]], label %[[CONT60:.*]], !annotation [[META5]] +// CHECK: [[BOUNDSCHECK_NOTNULL54]]: +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr [[STRUCT_OUTER]], ptr [[WIDE_PTR_PTR49]], i64 1, !annotation [[META11]] +// CHECK-NEXT: [[TMP28:%.*]] = icmp ule ptr [[TMP27]], [[WIDE_PTR_UB51]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[TMP28]], label %[[CONT56:.*]], label %[[TRAP55:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP55]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT56]]: +// CHECK-NEXT: [[TMP29:%.*]] = icmp ule ptr [[WIDE_PTR_PTR49]], [[TMP27]], !annotation [[META11]] +// CHECK-NEXT: br i1 [[TMP29]], label %[[CONT58:.*]], label %[[TRAP57:.*]], !prof [[PROF3]], !annotation [[META11]] +// CHECK: [[TRAP57]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META11]] +// CHECK-NEXT: unreachable, !annotation [[META11]] +// CHECK: [[CONT58]]: +// CHECK-NEXT: [[TMP30:%.*]] = icmp uge ptr [[WIDE_PTR_PTR49]], [[WIDE_PTR_LB53]], !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP30]], label %[[CONT60]], label %[[TRAP59:.*]], !prof [[PROF3]], !annotation [[META4]] +// CHECK: [[TRAP59]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] +// CHECK-NEXT: unreachable, !annotation [[META4]] +// CHECK: [[CONT60]]: +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR49]] // struct Outer * assign(void * __bidi_indexable bar, int len) { struct Outer * __single s = (struct Outer *) bar; @@ -261,11 +274,13 @@ struct Outer * assign(void * __bidi_indexable bar, int len) { } //. // CHECK: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} -// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} -// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-neq-null"} -// CHECK: [[META5]] = !{!"bounds-safety-check-one-past-end-overflow"} -// CHECK: [[META6]] = !{!"bounds-safety-check-count-negative"} -// CHECK: [[META7]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-le-upper-bound"} -// CHECK: [[META8]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-ge-lower-bound"} -// CHECK: [[META9]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META5]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META6]] = !{!"bounds-safety-check-one-past-end-overflow"} +// CHECK: [[META7]] = !{!"bounds-safety-check-count-negative"} +// CHECK: [[META8]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[META9]] = !{!"bounds-safety-check-flexible-count-gt-bounds", !"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[META10]] = !{!"bounds-safety-check-flexible-count-gt-bounds"} +// CHECK: [[META11]] = !{!"bounds-safety-check-ptr-le-upper-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-binop-overflow.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-binop-overflow.c index 98ecbba52ed3f..290ca8858afbd 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-binop-overflow.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-binop-overflow.c @@ -73,9 +73,9 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_shl // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -99,7 +99,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_shl // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -214,7 +214,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -231,12 +231,12 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_shl // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '5' +// OPT-REM-NEXT: - count: '8' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-missed-optimization-nuw, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-missed-optimization-nuw, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -244,13 +244,16 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: other (LLVM IR 'shl') -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') // OPT-REM-EMPTY: -// OPT-REM-NEXT: - String: "Missed Optimization Info\n" -// OPT-REM-NEXT: - String: Check can not be removed because the arithmetic operation might wrap in the unsigned sense. Optimize the check by adding conditions to check for overflow before doing the operation +// OPT-REM-NEXT: - String: "Missed Optimization Info\n" +// OPT-REM-NEXT: - String: Check can not be removed because the arithmetic operation might wrap in the unsigned sense. Optimize the check by adding conditions to check for overflow before doing the operation // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -287,9 +290,9 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_mul // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -313,7 +316,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_mul // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -428,7 +431,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -445,12 +448,12 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_mul // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '5' +// OPT-REM-NEXT: - count: '8' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-missed-optimization-nuw, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-missed-optimization-nuw, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -458,12 +461,17 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: other (LLVM IR 'shl') -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') // OPT-REM-EMPTY: -// OPT-REM: ... +// OPT-REM-NEXT: - String: "Missed Optimization Info\n" +// OPT-REM-NEXT: - String: Check can not be removed because the arithmetic operation might wrap in the unsigned sense. Optimize the check by adding conditions to check for overflow before doing the operation +// OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis // OPT-REM-NEXT: Pass: annotation-remarks @@ -501,7 +509,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: - String: 'Annotated ' // OPT-REM-NEXT: - count: '2' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -640,7 +648,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -683,9 +691,9 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_sub // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -709,7 +717,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_sub // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -824,7 +832,7 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -841,19 +849,22 @@ void test_sub(int* __indexable A, int N) { // OPT-REM-NEXT: Function: test_sub // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-ptr-induction.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-ptr-induction.c index c6601febc38ef..f1beb744b5269 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-ptr-induction.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-missed-ptr-induction.c @@ -78,9 +78,9 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -104,7 +104,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '3' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-missed-optimization-phi-step-size // OPT-REM-NEXT: ... @@ -117,7 +117,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -208,7 +208,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -225,19 +225,22 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -280,9 +283,9 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign_2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '6' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -306,7 +309,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign_2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '3' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-missed-optimization-phi-step-size // OPT-REM-NEXT: ... @@ -319,7 +322,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign_2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '15' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -410,7 +413,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -427,19 +430,21 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_sign_2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '6' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -482,9 +487,9 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -508,7 +513,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '3' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-missed-optimization-phi-step-size // OPT-REM-NEXT: ... @@ -521,7 +526,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -636,7 +641,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -653,19 +658,22 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -708,9 +716,9 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -734,7 +742,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '3' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-missed-optimization-phi-step-size // OPT-REM-NEXT: ... @@ -747,7 +755,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '13' +// OPT-REM-NEXT: - count: '16' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -862,7 +870,7 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-generic, bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} @@ -879,19 +887,22 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: Function: ptr_induction_different_step_size2 // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-missed-optimization-phi-step-size, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-EMPTY: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -901,3 +912,4 @@ void ptr_induction_different_step_size2(int* __indexable A, int N) { // OPT-REM-NEXT: ... // OPT-REM-NOT: --- !Analysis + diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-ptr-conversion-O2.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-ptr-conversion-O2.c index fdda5f4c54263..c8ec0dcac22c8 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-ptr-conversion-O2.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/bounds-safety-ptr-conversion-O2.c @@ -1,5 +1,5 @@ // REQUIRES: system-darwin - +// // RUN: %clang_cc1 -triple x86_64-apple-macos -Wno-bounds-safety-init-list -fbounds-safety -O2 %s -emit-llvm -o %t-O2.s -opt-record-file %t-O2.opt.yaml -opt-record-format yaml // RUN: FileCheck --input-file %t-O2.s --check-prefixes IR %s // RUN: FileCheck --input-file %t-O2.opt.yaml --check-prefixes OPT-REM %s diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O0.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O0.c index 1741e2a00aaa9..5f03c4aaedf21 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O0.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O0.c @@ -18,20 +18,30 @@ int main(int argc, char **argv) { // IR-LABEL: @foo // ... -// IR: icmp ult {{.*}} !dbg ![[LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB:[0-9]+]] -// IR: br i1 %{{[0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] +// IR: icmp ule ptr %{{.*}}, %{{.*}}, !dbg ![[LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LE_UB:[0-9]+]] +// IR-NEXT: br i1 %7, label %[[FOO_LABEL_CONT_0:[a-z0-9]+]], label %[[FOO_LABEL_TRAP_0:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LE_UB]] // ... -// IR: [[FOO_LABEL_TRAP]]: -// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB]] -// IR-NEXT: unreachable, !dbg ![[LT_TRAP_LOC_10_16]], !annotation ![[ANNOT_LT_UB]] -// ... -// IR: [[FOO_LABEL_CONT]]: -// IR: icmp uge {{.*}} !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[0-9]+]] -// IR: br i1 %{{[0-9]+}}, label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP2:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_GE_LB]] -// ... -// IR: [[FOO_LABEL_TRAP2]]: -// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[GE_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_GE_LB]] -// IR-NEXT: unreachable, !dbg ![[GE_TRAP_LOC_10_16]], !annotation ![[ANNOT_GE_LB]] + +// IR: [[FOO_LABEL_TRAP_0]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: unreachable, !dbg !{{.*}}, !annotation ![[ANNOT_LE_UB]] + +// IR: [[FOO_LABEL_CONT_0]]: +// IR: icmp ule ptr %{{.*}}, %{{.*}}, !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: br i1 %8, label %[[FOO_LABEL_CONT_1:[a-z0-9]+]], label %[[FOO_LABEL_TRAP_1:[a-z0-9]+]], !dbg !11, !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LE_UB]] + +// IR: [[FOO_LABEL_TRAP_1]]: +// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{.*}}, !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: unreachable, !dbg !{{.*}}, !annotation ![[ANNOT_LE_UB]] + +// IR:[[FOO_LABEL_CONT_1]]: +// IR-NEXT: icmp uge ptr %{{.*}}, %{{.*}}, !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[a-z0-9]+]] +// IR-NEXT: br i1 %{{.*}}, label %[[FOO_LABEL_CONT_2:[a-z0-9]+]], label %[[FOO_LABEL_TRAP_2:[a-z0-9]+]], !dbg !11, !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_GE_LB]] + +// IR: [[FOO_LABEL_TRAP_2]]: +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{.*}}, !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: unreachable, !dbg !{{.*}}, !annotation ![[ANNOT_GE_LB]] + // IR-LABEL: @main // IR: entry @@ -62,20 +72,14 @@ int main(int argc, char **argv) { // IR-DAG: ![[ANNOT_AUTO_INIT]] = !{!"bounds-safety-zero-init"} // IR-DAG: ![[LOC_10_16]] = !DILocation(line: 10, column: 16{{.*}}) -// IR-DAG: ![[LT_TRAP_LOC_10_16]] = !DILocation(line: 0, scope: ![[LT_TRAP_INFO_10_16:[0-9]+]], inlinedAt: ![[LOC_10_16]]) -// IR-DAG: ![[LT_TRAP_INFO_10_16]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds" -// IR-DAG: ![[GE_TRAP_LOC_10_16]] = !DILocation(line: 0, scope: ![[GE_TRAP_INFO_10_16:[0-9]+]], inlinedAt: ![[LOC_10_16]]) -// IR-DAG: ![[GE_TRAP_INFO_10_16]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing below bounds" // // IR-DAG: ![[LOC_16_5]] = !DILocation(line: 16, column: 5 -// IR-DAG: ![[TRAP_LOC_16_5]] = !DILocation(line: 0, scope: ![[TRAP_INFO_16_5:[0-9]+]], inlinedAt: ![[LOC_16_5]]) -// IR-DAG: ![[TRAP_INFO_16_5]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$" -// IR-DAG: ![[TRAP_LOC_MISSING]] = !DILocation(line: 0, scope: ![[MAIN_SCOPE:[0-9]+]]) -// IR-DAG: ![[MAIN_SCOPE]] = distinct !DISubprogram(name: "main", {{.*}} line: 13, {{.*}} scopeLine: 13 +// IR-DAG: [[ANNOT_LE_UB]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// IR-DAG: [[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} -// opt-remarks tests generated using `gen-opt-remarks-check-lines.py` +// opt-remarks tests generated using `gen-opt-remarks-check-lines.py` // OPT-REM: --- !Analysis // OPT-REM-NEXT: Pass: annotation-remarks @@ -85,9 +89,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -111,7 +115,7 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '8' +// OPT-REM-NEXT: - count: '13' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -124,16 +128,21 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') // OPT-REM-NEXT: cond branch (LLVM IR 'br') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -147,15 +156,21 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '4' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: -// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -173,7 +188,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" // OPT-REM-NEXT: ... @@ -231,7 +248,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-zero-init // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: 'call (LLVM IR ''call'')' // OPT-REM-NEXT: ... @@ -250,7 +269,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-generic // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: call (LLVM IR 'call') // OPT-REM-NEXT: other (LLVM IR 'getelementptr') @@ -327,7 +348,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-generic // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -352,7 +375,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-generic // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: 'other (LLVM IR ''zext'')' // OPT-REM-NEXT: ... @@ -371,7 +396,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-generic // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: 'other (LLVM IR ''phi'')' // OPT-REM-NEXT: ... @@ -390,7 +417,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: "used for:\n" // OPT-REM-NEXT: - String: bounds-safety-generic // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" // OPT-REM-NEXT: ... diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O2.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O2.c index 521d644d04033..3f1c1741cc034 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O2.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-argc-O2.c @@ -22,28 +22,37 @@ int main(int argc, char **argv) { // IR-NEXT: %[[UPPER_BOUND:[a-z0-9.]+]] = getelementptr inbounds nuw i32, ptr %[[ARR:[a-z0-9.]+]], i64 %[[COUNT_EXT]], !dbg ![[LOC_10_5]] // IR-NEXT: %[[IDX_EXT:[a-z0-9.]+]] = zext i32 {{.*}} to i64, !dbg ![[LOC_10_16:[0-9]+]] // IR-NEXT: %[[PTR:[a-z0-9.]+]] = getelementptr i32, ptr %[[ARR]], i64 %[[IDX_EXT]], !dbg ![[LOC_10_16]] -// IR-NEXT: %[[UPPER_CHECK:[a-z0-9.]+]] = icmp ult ptr %[[PTR]], %[[UPPER_BOUND]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LT_UB:[0-9]+]] -// IR-NEXT: %[[LOWER_CHECK:[a-z0-9.]+]] = icmp uge ptr %[[PTR]], %[[ARR]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[0-9]+]] -// TODO: The condition and branch should also be ANNOT_LT_UB_OR_GT_LB (rdar://109089053) -// IR-NEXT: %[[COND:[a-z0-9.]+]] = and i1 %[[UPPER_CHECK]], %[[LOWER_CHECK]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB]] -// IR-NEXT: br i1 %{{[a-z.0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] -// ... + +// IR-NEXT: %[[ONE_PAST_END:[a-z0-9.]+]] = getelementptr i8, ptr %[[PTR]], i64 4, !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LE_UB:[0-9]+]] +// IR-NEXT: %[[UPPER_CHECK:[a-z0-9.]+]] = icmp ule ptr %[[ONE_PAST_END]], %[[UPPER_BOUND]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[OVERFLOW_CHECK:[a-z0-9.]+]] = icmp ule ptr %[[PTR]], %[[ONE_PAST_END]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[COND_AND_0:[a-z0-9.]+]] = and i1 %[[UPPER_CHECK]], %[[OVERFLOW_CHECK]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[LOWER_CHECK:[a-z0-9.]+]] = icmp uge ptr %[[PTR]], %[[ARR]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB:[0-9]+]] +// TODO: The condition and branch should both be annotated with ANNOT_GE_LB and ANNOT_LE_UB (rdar://109089053) +// IR-NEXT: %[[COND_AND_1:[a-z0-9.]+]] = and i1 %[[LOWER_CHECK]], %[[COND_AND_0]], !dbg ![[LOC_10_16]], !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: br i1 %[[COND_AND_1]], label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_16]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LE_UB]] + + + // IR: [[FOO_LABEL_TRAP]]: -// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_16:[0-9]+]], !annotation ![[ANNOT_LT_UB_OR_GE_LB:[0-9]+]] -// ... +// IR-NEXT: tail call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LOC_10_16]], !annotation ![[ANNOT_UB_AND_LB:[0-9]+]] +// IR-NEXT: unreachable, !dbg ![[LOC_10_16]], !annotation ![[ANNOT_UB_AND_LB]] +// // IR: [[FOO_LABEL_CONT]]: -// IR-NEXT: store {{.*}} !dbg ![[LOC_10_16]] +// IR-NEXT: store i32 42, ptr %[[PTR]],{{.*}} !dbg ![[LOC_10_16]] // IR-NEXT: ret + // IR-LABEL: @main // IR: entry // IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[TRAP_LOC_16_5:[0-9]+]] // IR-DAG: ![[LOC_10_5]] = !DILocation(line: 10, column: 5 // IR-DAG: ![[LOC_10_16]] = !DILocation(line: 10, column: 16 -// IR-DAG: ![[ANNOT_LT_UB]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// IR-DAG: ![[ANNOT_LE_UB]] = !{!"bounds-safety-check-ptr-le-upper-bound"} // IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} -// IR-DAG: ![[ANNOT_LT_UB_OR_GE_LB]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} +// IR-DAG: ![[ANNOT_UB_AND_LB]] = !{!"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} + // opt-rem checks autogenerated by gen-opt-remarks-check-lines.py @@ -65,7 +74,7 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: '''' // OPT-REM-NEXT: - String: ' with ' // OPT-REM-NEXT: - String: '(cost=' -// OPT-REM-NEXT: - Cost: '-15' +// OPT-REM-NEXT: - Cost: '-5' // OPT-REM-NEXT: - String: ', threshold=' // OPT-REM-NEXT: - Threshold: '225' // OPT-REM-NEXT: - String: ')' @@ -86,9 +95,9 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -112,7 +121,7 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -125,16 +134,21 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -152,7 +166,7 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: 'Annotated ' // OPT-REM-NEXT: - count: '1' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -194,10 +208,13 @@ int main(int argc, char **argv) { // OPT-REM-NEXT: - String: '' // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | -// OPT-REM: instructions: +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: {{^[ ]+$}} +// OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: 'other (LLVM IR ''unreachable'')' // OPT-REM-NEXT: ... // OPT-REM-NOT: --- !Analysis + diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O0.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O0.c index 95b104d1ae7dc..9400288238a73 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O0.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O0.c @@ -16,21 +16,34 @@ int main() { foo(a, n); } -// IR-LABEL: @foo -// ... -// IR: icmp ult {{.*}} !dbg ![[LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB:[0-9]+]] -// IR: br i1 %{{[0-9]+}}, label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LT_UB]] -// ... -// IR: [[FOO_LABEL_TRAP]]: -// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LT_TRAP_LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB]] -// IR-NEXT: unreachable, !dbg ![[LT_TRAP_LOC_10_14]], !annotation ![[ANNOT_LT_UB]] -// ... -// IR: [[FOO_LABEL_CONT]]: -// IR: br i1 %{{[0-9]+}}, label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP2:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA]], !annotation ![[ANNOT_GE_LB:[0-9]+]] -// ... -// IR: [[FOO_LABEL_TRAP2]]: -// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[GT_TRAP_LOC_10_14:[0-9]+]], !annotation ![[ANNOT_GE_LB]] -// IR-NEXT: unreachable, !dbg ![[GT_TRAP_LOC_10_14]], !annotation ![[ANNOT_GE_LB]] +// IR: %[[ONE_PAST_END:[a-z0-9.]+]] = getelementptr i32, ptr %[[PTR:[a-z0-9._]+]], i64 1, !dbg ![[LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LE_UB:[0-9]+]] +// IR-NEXT: %[[UPPER_CHECK:[a-z0-9.]+]] = icmp ule ptr %[[ONE_PAST_END]], %[[UPPER_BOUND:[a-z0-9._]+]], !dbg ![[LOC_10_14]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: br i1 %[[UPPER_CHECK]], label %[[FOO_LABEL_CONT_0:[a-z0-9.]+]], label %[[FOO_LABEL_TRAP_0:[a-z0-9.]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LE_UB]] +// +// IR: [[FOO_LABEL_TRAP_0:]]: +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: unreachable, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// +// IR: [[FOO_LABEL_CONT_0]]: +// IR-NEXT: %[[OVERFLOW_CHECK:[a-z0-9.]+]] = icmp ule ptr %[[PTR]], %[[ONE_PAST_END]], !dbg ![[LOC_10_14]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: br i1 %[[OVERFLOW_CHECK]], label %[[FOO_LABEL_CONT_1:[a-z0-9.]+]], label %[[FOO_LABEL_TRAP_1:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_LE_UB]] +// +// IR: [[FOO_LABEL_TRAP_1]]: +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: unreachable, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// +// IR: [[FOO_LABEL_CONT_1]]: +// IR-NEXT: %[[LOWER_CHECK:[a-z0-9.]+]] = icmp uge ptr %[[PTR]], %[[LOWER_BOUND:[a-z0-9._]+]], !dbg ![[LOC_10_14]], !annotation ![[ANNOT_GE_LB:[0-9]+]] +// IR-NEXT: br i1 %[[LOWER_CHECK]], label %[[FOO_LABEL_CONT_2:[a-z0-9.]+]], label %[[FOO_LABEL_TRAP_2:[a-z0-9]+]], !dbg ![[LOC_10_14]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation ![[ANNOT_GE_LB]] +// +// IR: [[FOO_LABEL_TRAP_2]]: +// IR-NEXT: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: unreachable, !dbg !{{[0-9]+}}, !annotation ![[ANNOT_GE_LB]] +// +// IR: [[FOO_LABEL_CONT_2]]: +// IR-NEXT: store i32 42, ptr %[[PTR]]{{.*}}, !dbg ![[LOC_10_14]] +// IR-NEXT: ret + // IR-LABEL: @main @@ -61,17 +74,12 @@ int main() { // IR-DAG: ![[ANNOT_CONV_TO_COUNT]] = !{!"bounds-safety-generic"} // IR-DAG: ![[ANNOT_AUTO_INIT]] = !{!"bounds-safety-zero-init"} +// IR-DAG: ![[ANNOT_LE_UB]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} + // IR-DAG: ![[LOC_10_14]] = !DILocation(line: 10, column: 14{{.*}}) -// IR-DAG: ![[LT_TRAP_LOC_10_14]] = !DILocation(line: 0, scope: ![[LT_TRAP_INFO_10_14:[0-9]+]], inlinedAt: ![[LOC_10_14]]) -// IR-DAG: ![[LT_TRAP_INFO_10_14]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds" -// IR-DAG: ![[GT_TRAP_LOC_10_14]] = !DILocation(line: 0, scope: ![[GT_TRAP_INFO_10_14:[0-9]+]], inlinedAt: ![[LOC_10_14]]) -// IR-DAG: ![[GT_TRAP_INFO_10_14]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing below bounds" // IR-DAG: ![[LOC_16_5]] = !DILocation(line: 16, column: 5 -// IR-DAG: ![[TRAP_LOC_16_5]] = !DILocation(line: 0, scope: ![[TRAP_INFO_16_5:[0-9]+]], inlinedAt: ![[LOC_16_5]]) -// IR-DAG: ![[TRAP_INFO_16_5]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$" -// IR-DAG: ![[TRAP_LOC_MISSING]] = !DILocation(line: 0, scope: ![[MAIN_SCOPE:[0-9]+]]) -// IR-DAG: ![[MAIN_SCOPE]] = distinct !DISubprogram(name: "main", {{.*}} line: 13, {{.*}} scopeLine: 13 // opt-remarks tests generated using `gen-opt-remarks-check-lines.py` @@ -83,9 +91,9 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -109,7 +117,7 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '8' +// OPT-REM-NEXT: - count: '13' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -122,18 +130,21 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cond branch (LLVM IR 'br') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') // OPT-REM-NEXT: cond branch (LLVM IR 'br') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: cond branch (LLVM IR 'br') @@ -147,17 +158,21 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '2' +// OPT-REM-NEXT: - count: '4' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: -// OPT-REM-NEXT: - String: "trap (LLVM IR 'call')\nother (LLVM IR 'unreachable')" +// OPT-REM-NEXT: - String: | +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') +// OPT-REM-NEXT: trap (LLVM IR 'call') +// OPT-REM-NEXT: other (LLVM IR 'unreachable') // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis diff --git a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O2.c b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O2.c index 736aef8740092..fd79471645942 100644 --- a/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O2.c +++ b/clang/test/BoundsSafety/CodeGen/opt-remarks/ptr-bounds-const-O2.c @@ -17,16 +17,26 @@ int main() { } // IR-LABEL: @foo -// ... -// IR-DAG: icmp ult ptr {{.*}}, !dbg {{.+}}, !annotation ![[ANNOT_LT_UB:[0-9]+]] -// IR-DAG: icmp uge ptr {{%.*}}, !dbg {{.+}}, !annotation ![[ANNOT_GE_LB:[0-9]+]] -// IR: [[OR_COND:%.*]] = and i1 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}, !dbg {{.+}}, !annotation ![[ANNOT_GE_LB]] -// IR: br i1 [[OR_COND]], label %{{[a-z0-9]+}}, label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg {{.+}}, !annotation ![[ANNOT_LT_UB]] -// ... -// IR: [[FOO_LABEL_TRAP]]: -// IR: call void @llvm.ubsantrap(i8 25) #{{[0-9]+}}, !dbg ![[LOC_10_14:[0-9]+]], !annotation ![[ANNOT_LT_UB_AND_GE_LB:[0-9]+]] -// IR-NEXT: unreachable, !dbg ![[LOC_10_14]], !annotation ![[ANNOT_LT_UB_AND_GE_LB]] +// IR: %[[UPPER_BOUND:.+]] = getelementptr inbounds nuw i32, ptr %[[ARRAY:.+]], i64 %{{.+}}, !dbg !{{.+}} +// IR-NEXT: %[[PTR:.+]] = getelementptr i8, ptr %[[ARRAY]], i64 24, !dbg ![[LOC_FOO:[0-9]+]] +// IR-NEXT: %[[ONE_PAST_END:.+]] = getelementptr i8, ptr %[[ARRAY]], i64 28, !dbg ![[LOC_FOO]], !annotation ![[ANNOT_LE_UB:[0-9]+]] +// IR-NEXT: %[[UPPER_CHECK:.+]] = icmp ule ptr %[[ONE_PAST_END]], %[[UPPER_BOUND]], !dbg ![[LOC_FOO]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[OVERFLOW_CHECK:.+]] = icmp ule ptr %[[PTR]], %[[ONE_PAST_END]], !dbg ![[LOC_FOO]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[UPPER_AND_OVERFLOW_CHECK:.+]] = and i1 %[[OVERFLOW_CHECK]], %[[UPPER_CHECK]], !dbg ![[LOC_FOO]], !annotation ![[ANNOT_LE_UB]] +// IR-NEXT: %[[LOWER_CHECK:.+]] = icmp uge ptr %[[PTR]], %[[ARRAY]], !dbg ![[LOC_FOO]], !annotation ![[ANNOT_GE_LB:[0-9]+]] + +// FIXME: opt-remarks on `and` and `br` should be `ANNOT_COMBINED` (rdar://109089053) +// IR-NEXT: %[[COMBINED_CHECKS:.+]] = and i1 %[[LOWER_CHECK]], %[[UPPER_AND_OVERFLOW_CHECK]], !dbg ![[LOC_FOO]], !annotation ![[ANNOT_GE_LB]] +// IR-NEXT: br i1 %[[COMBINED_CHECKS]], label %[[FOO_LABEL_CONT:[a-z0-9]+]], label %[[FOO_LABEL_TRAP:[a-z0-9]+]], !dbg ![[LOC_FOO]], !prof !{{[0-9]+}}, !annotation ![[ANNOT_LE_UB]] +// +// IR: [[FOO_LABEL_TRAP]]: +// IR-NEXT: tail call void @llvm.ubsantrap(i8 25) #3, !dbg ![[LOC_FOO]], !annotation ![[ANNOT_COMBINED:[0-9]+]] +// IR-NEXT: unreachable, !dbg ![[LOC_FOO]], !annotation ![[ANNOT_COMBINED]] +// +// IR: [[FOO_LABEL_CONT]]: +// IR-NEXT: store i32 42, ptr %[[PTR]],{{.+}} !dbg ![[LOC_FOO]] +// IR-NEXT: ret // IR-LABEL: @main // ... @@ -34,11 +44,13 @@ int main() { // IR-NEXT: unreachable, !dbg ![[LOC_0]], !annotation ![[ANNOT_LE_UB_AND_CONV_TO_COUNT]] -// IR-DAG: ![[ANNOT_LT_UB]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} -// IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} -// IR-DAG: ![[ANNOT_LT_UB_AND_GE_LB]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} // IR-DAG: ![[ANNOT_LE_UB_AND_CONV_TO_COUNT]] = !{!"bounds-safety-generic"} +// IR-DAG: ![[LOC_FOO:[0-9]+]] = !DILocation(line: 10, column: 14, scope: !5) +// IR-DAG: ![[ANNOT_LE_UB]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// IR-DAG: ![[ANNOT_GE_LB]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// IR-DAG: ![[ANNOT_COMBINED]] = !{!"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"} + // opt-remarks tests generated using `gen-opt-remarks-check-lines.py` // OPT-REM: --- !Analysis @@ -49,9 +61,9 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '4' +// OPT-REM-NEXT: - count: '7' // OPT-REM-NEXT: - String: ' instructions with ' -// OPT-REM-NEXT: - type: bounds-safety-check-ptr-lt-upper-bound +// OPT-REM-NEXT: - type: bounds-safety-check-ptr-le-upper-bound // OPT-REM-NEXT: ... // OPT-REM-NEXT: --- !Analysis @@ -75,7 +87,7 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Annotated ' -// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' instructions with ' // OPT-REM-NEXT: - type: bounds-safety-total-summary // OPT-REM-NEXT: ... @@ -88,18 +100,21 @@ int main() { // OPT-REM-NEXT: Function: foo // OPT-REM-NEXT: Args: // OPT-REM-NEXT: - String: 'Inserted ' -// OPT-REM-NEXT: - count: '6' +// OPT-REM-NEXT: - count: '9' // OPT-REM-NEXT: - String: ' LLVM IR instruction' // OPT-REM-NEXT: - String: s // OPT-REM-NEXT: - String: "\n" // OPT-REM-NEXT: - String: "used for:\n" -// OPT-REM-NEXT: - String: bounds-safety-check-ptr-lt-upper-bound, bounds-safety-check-ptr-ge-lower-bound +// OPT-REM-NEXT: - String: bounds-safety-check-ptr-le-upper-bound, bounds-safety-check-ptr-ge-lower-bound // OPT-REM-NEXT: - String: | // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: {{^[ ]+$}} // OPT-REM-NEXT: instructions: // OPT-REM-NEXT: - String: | -// OPT-REM-NEXT: cmp ult (LLVM IR 'icmp') +// OPT-REM-NEXT: other (LLVM IR 'getelementptr') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: cmp ule (LLVM IR 'icmp') +// OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cmp uge (LLVM IR 'icmp') // OPT-REM-NEXT: and (LLVM IR 'and') // OPT-REM-NEXT: cond branch (LLVM IR 'br') diff --git a/clang/test/BoundsSafety/CodeGen/ptr-arith-O2.c b/clang/test/BoundsSafety/CodeGen/ptr-arith-O2.c index cf1ac5d2170d0..186d5408221c9 100644 --- a/clang/test/BoundsSafety/CodeGen/ptr-arith-O2.c +++ b/clang/test/BoundsSafety/CodeGen/ptr-arith-O2.c @@ -17,14 +17,17 @@ struct T { // CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds i32, ptr [[BUF:%.*]], i64 [[IDX_EXT]] // CHECK-NEXT: [[IDX_NEG:%.*]] = sub nsw i64 0, [[IDX_EXT]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[BOUND_PTR_ARITH5:%.*]] = getelementptr i32, ptr [[BUF]], i64 [[IDX_NEG]] -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH5]], [[ADD_PTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5]], [[BUF]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT6:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BOUND_PTR_ARITH5]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[BOUND_PTR_ARITH5]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5]], [[BUF]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND8:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND8]], label [[CONT7:%.*]], label [[TRAP:%.*]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont6: +// CHECK: cont7: // CHECK-NEXT: store i32 3, ptr [[BOUND_PTR_ARITH5]], align 4, {{!tbaa ![0-9]+}} // CHECK-NEXT: ret void // @@ -40,10 +43,13 @@ void foo(int *buf __counted_by(len), int len) { // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[A]]) #[[ATTR4:[0-9]+]] // CHECK-NEXT: [[ADD_PTR3_I:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 40 // CHECK-NEXT: [[BOUND_PTR_ARITH5_I:%.*]] = getelementptr i8, ptr [[A]], i64 -40 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH5_I]], [[ADD_PTR3_I]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5_I]], [[A]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[FOO_EXIT:%.*]], label [[TRAP_I:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[A]], i64 -36, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR3_I]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[BOUND_PTR_ARITH5_I]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH5_I]], [[A]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND8_I:%.*]] = and i1 [[TMP3]], [[OR_COND_I]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND8_I]], label [[FOO_EXIT:%.*]], label [[TRAP_I:%.*]], !prof [[PROF6]], {{!annotation ![0-9]+}} // CHECK: trap.i: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} diff --git a/clang/test/BoundsSafety/CodeGen/ptr-arith.c b/clang/test/BoundsSafety/CodeGen/ptr-arith.c index b27efdfda205c..bccbea111c971 100644 --- a/clang/test/BoundsSafety/CodeGen/ptr-arith.c +++ b/clang/test/BoundsSafety/CodeGen/ptr-arith.c @@ -81,18 +81,25 @@ __attribute__((noinline)) // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP30]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP31:%.*]] = icmp ule ptr [[TMP30]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP31]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP31:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP31]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP32:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP30]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP32]], label [[CONT7:%.*]], label [[TRAP6:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap6: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont7: +// CHECK-NEXT: [[TMP33:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP33]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: // CHECK-NEXT: store i32 3, ptr [[WIDE_PTR_PTR]], align 4 // CHECK-NEXT: ret void // @@ -121,10 +128,10 @@ void foo(int *buf __counted_by(len), int len) { // CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 // CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound-lower.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound-lower.c index 1296026b7dbdf..b975974a7e5a6 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound-lower.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound-lower.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s // RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s // RUN: %clang_cc1 -O2 -fbounds-safety -triple arm -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-ARM-O2 %s @@ -35,7 +34,7 @@ // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} // CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} @@ -76,54 +75,37 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP6]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 -// CHECK-O0-NEXT: [[TMP18:%.*]] = icmp ult ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP18]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP18:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP19:%.*]] = icmp ule ptr [[TMP18]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP19]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap13: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont14: -// CHECK-O0-NEXT: [[TMP19:%.*]] = icmp uge ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP19]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP20:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP18]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP20]], label [[CONT16:%.*]], label [[TRAP15:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap15: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont16: -// CHECK-O0-NEXT: [[TMP20:%.*]] = load i32, ptr [[WIDE_PTR_PTR8]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP20]] +// CHECK-O0-NEXT: [[TMP21:%.*]] = icmp uge ptr [[WIDE_PTR_PTR8]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP21]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap17: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont18: +// CHECK-O0-NEXT: [[TMP22:%.*]] = load i32, ptr [[WIDE_PTR_PTR8]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP22]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: -// CHECK-O2-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 -// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3:[0-9]+]] -// CHECK-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 40 -// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i64 -4 -// CHECK-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: br i1 [[OR_COND]], label [[CONT14:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O2: trap: -// CHECK-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-O2: cont14: -// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3]] -// CHECK-O2-NEXT: ret i32 undef // // CHECK-ARM-O2-LABEL: @main( // CHECK-ARM-O2-NEXT: entry: -// CHECK-ARM-O2-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 4 -// CHECK-ARM-O2-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3:[0-9]+]] -// CHECK-ARM-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i32 40 -// CHECK-ARM-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[ARR]], i32 -4 -// CHECK-ARM-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-ARM-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[ARR]], {{!annotation ![0-9]+}} -// CHECK-ARM-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-ARM-O2-NEXT: br i1 [[OR_COND]], label [[CONT14:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-ARM-O2: trap: -// CHECK-ARM-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-ARM-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-ARM-O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-ARM-O2: cont14: -// CHECK-ARM-O2-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR3]] -// CHECK-ARM-O2-NEXT: ret i32 undef // int main() { int arr[10]; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound.c index 35f6ed61068f2..d4376bb6cfb8f 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/array-to-bound.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s @@ -11,17 +10,20 @@ // O2-LABEL: @foo( // O2-NEXT: entry: // O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR:%.*]], i64 4 -// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 40 -// O2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} -// O2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[ARR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 40 +// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 44, {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} -// O2-NEXT: br i1 [[OR_COND]], label [[CONT11:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND13:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND13]], label [[CONT12:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // O2: trap: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// O2: cont11: -// O2-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} -// O2-NEXT: ret i32 [[TMP3]] +// O2: cont12: +// O2-NEXT: [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP4]] // // O0-LABEL: @foo( // O0-NEXT: entry: @@ -64,25 +66,32 @@ // O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 // O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 -// O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 +// O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 // O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 // O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP10]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP11]], label [[CONT12:%.*]], label [[TRAP11:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP11:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP9]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[CONT12:%.*]], label [[TRAP11:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap11: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont12: -// O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// O0-NEXT: ret i32 [[TMP12]] +// O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap13: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont14: +// O0-NEXT: [[TMP13:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// O0-NEXT: ret i32 [[TMP13]] // int foo(int * arr) { int *__indexable uPtr = arr; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array-ok.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array-ok.c index 64fa2c567c794..b3ed38859fea4 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array-ok.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array-ok.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix CHECK-O0 %s @@ -30,13 +29,13 @@ // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} // CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: // CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 0 // CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP4]], align 8 @@ -57,25 +56,32 @@ // CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 -// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 9 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 9 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 -// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap13: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont14: -// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap15: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont16: -// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP12]] +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap17: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont18: +// CHECK-O0-NEXT: [[TMP13:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP13]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array.c index b0f510e08b7b1..073a6bda379a7 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/bound-to-array.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s @@ -29,13 +28,13 @@ // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} // CHECK-O0-NEXT: [[TMP3:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: // CHECK-O0-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[P]], i32 0, i32 0 // CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP4]], align 8 @@ -54,30 +53,37 @@ // CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR4]], ptr [[TMP8]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8 -// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR8]], i64 10 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8 -// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap13: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont14: -// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT16:%.*]], label [[TRAP15:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap15: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont16: -// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP12]] +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT18:%.*]], label [[TRAP17:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap17: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont18: +// CHECK-O0-NEXT: [[TMP13:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP13]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int arr[10]; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-bound.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-bound.c index 737b2bc4ebf81..838a8b9f00bdc 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-bound.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-bound.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -Wno-bounds-safety-init-list -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s @@ -30,31 +29,31 @@ // O0-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 // O0-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN]], align 4 // O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 -// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 -// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 -// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 -// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 -// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] -// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 -// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] -// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} // O0: land.rhs: -// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] -// O0-NEXT: br label [[LAND_END]] +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// O0-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} // O0: land.end: // O0-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: // O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) // O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 @@ -83,20 +82,27 @@ // O0-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 -// O0-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP11]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR16]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap21: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont22: -// O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP12]], label [[CONT24:%.*]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR16]], [[TMP11]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap23: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont24: -// O0-NEXT: [[TMP13:%.*]] = load i32, ptr [[WIDE_PTR_PTR16]], align 4 -// O0-NEXT: ret i32 [[TMP13]] +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT26:%.*]], label [[TRAP25:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap25: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont26: +// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR16]], align 4 +// O0-NEXT: ret i32 [[TMP15]] // int main() { int len = 0; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-thin.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-thin.c index 0423873ff0752..d3ed5cac3741a 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-thin.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/dep-count-ptr-to-thin.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s @@ -33,31 +32,31 @@ // O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP3]], align 8 // O0-NEXT: [[TMP4:%.*]] = load i32, ptr [[LEN]], align 4 // O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP4]] to i64 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 -// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 -// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 -// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 -// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 -// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] -// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 -// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] -// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} // O0: land.rhs: -// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] -// O0-NEXT: br label [[LAND_END]] +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// O0-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} // O0: land.end: // O0-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: // O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) // O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 @@ -86,24 +85,31 @@ // O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 // O0-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR16]], null, {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT24:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT26:%.*]], {{!annotation ![0-9]+}} // O0: boundscheck.notnull: -// O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP12]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR16]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap21: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont22: -// O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP13]], label [[CONT24]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR16]], [[TMP12]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap23: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont24: +// O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP15]], label [[CONT26]], label [[TRAP25:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap25: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont26: // O0-NEXT: store ptr [[WIDE_PTR_PTR16]], ptr [[TP]], align 8 -// O0-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TP]], align 8 -// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4 -// O0-NEXT: ret i32 [[TMP15]] +// O0-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TP]], align 8 +// O0-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 +// O0-NEXT: ret i32 [[TMP17]] // int foo(int len_init) { int i[3] = {3}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/dependent-count-pointer-conversion.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/dependent-count-pointer-conversion.c index 6049ffb46a9ce..3ab2bfe2eb89a 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/dependent-count-pointer-conversion.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/dependent-count-pointer-conversion.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s @@ -21,7 +20,7 @@ // O0-NEXT: [[TP:%.*]] = alloca ptr, align 8 // O0-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // O0-NEXT: [[BP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// O0-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// O0-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 // O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[ARR]], ptr align 16 @__const.main.arr, i64 40, i1 false) // O0-NEXT: store i32 5, ptr [[LEN]], align 4 @@ -35,31 +34,31 @@ // O0-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 // O0-NEXT: [[TMP3:%.*]] = load i32, ptr [[LEN]], align 4 // O0-NEXT: [[CONV:%.*]] = sext i32 [[TMP3]] to i64 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 -// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8 -// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 -// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64 -// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64 -// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] -// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4 -// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]] -// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR]] to i64, {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// O0-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// O0-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} // O0: land.rhs: -// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]] -// O0-NEXT: br label [[LAND_END]] +// O0-NEXT: [[CMP5:%.*]] = icmp sle i64 0, [[CONV]], {{!annotation ![0-9]+}} +// O0-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} // O0: land.end: // O0-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP5]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: // O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false) // O0-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 @@ -86,60 +85,74 @@ // O0-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP14]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8 // O0-NEXT: [[TMP10:%.*]] = icmp ne ptr [[WIDE_PTR_PTR16]], null, {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP10]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT24:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP10]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT26:%.*]], {{!annotation ![0-9]+}} // O0: boundscheck.notnull: -// O0-NEXT: [[TMP11:%.*]] = icmp ult ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP11]], label [[CONT22:%.*]], label [[TRAP21:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR16]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB18]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP12]], label [[CONT22:%.*]], label [[TRAP21:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap21: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont22: -// O0-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP12]], label [[CONT24]], label [[TRAP23:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR16]], [[TMP11]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP13]], label [[CONT24:%.*]], label [[TRAP23:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap23: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont24: +// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR16]], [[WIDE_PTR_LB20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT26]], label [[TRAP25:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap25: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont26: // O0-NEXT: store ptr [[WIDE_PTR_PTR16]], ptr [[TP]], align 8 -// O0-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DCP]], align 8 -// O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[LEN]], align 4 -// O0-NEXT: [[IDX_EXT25:%.*]] = sext i32 [[TMP14]] to i64 -// O0-NEXT: [[ADD_PTR26:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 [[IDX_EXT25]] -// O0-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 0 -// O0-NEXT: store ptr [[TMP13]], ptr [[TMP15]], align 8 -// O0-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 1 -// O0-NEXT: store ptr [[ADD_PTR26]], ptr [[TMP16]], align 8 -// O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 2 -// O0-NEXT: store ptr [[TMP13]], ptr [[TMP17]], align 8 +// O0-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DCP]], align 8 +// O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[LEN]], align 4 +// O0-NEXT: [[IDX_EXT27:%.*]] = sext i32 [[TMP16]] to i64 +// O0-NEXT: [[ADD_PTR28:%.*]] = getelementptr inbounds i32, ptr [[TMP15]], i64 [[IDX_EXT27]] +// O0-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 0 +// O0-NEXT: store ptr [[TMP15]], ptr [[TMP17]], align 8 +// O0-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 1 +// O0-NEXT: store ptr [[ADD_PTR28]], ptr [[TMP18]], align 8 +// O0-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[BP]], i32 0, i32 2 +// O0-NEXT: store ptr [[TMP15]], ptr [[TMP19]], align 8 // O0-NEXT: br label [[BINGO:%.*]] // O0: bingo: -// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[BP]], i64 24, i1 false) -// O0-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 -// O0-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8 -// O0-NEXT: [[TMP18:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR29]], i64 5 -// O0-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 -// O0-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8 -// O0-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 -// O0-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8 -// O0-NEXT: [[TMP19:%.*]] = icmp ult ptr [[TMP18]], [[WIDE_PTR_UB31]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP19]], label [[CONT35:%.*]], label [[TRAP34:%.*]], {{!annotation ![0-9]+}} -// O0: trap34: -// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable -// O0: cont35: -// O0-NEXT: [[TMP20:%.*]] = icmp uge ptr [[TMP18]], [[WIDE_PTR_LB33]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP20]], label [[CONT37:%.*]], label [[TRAP36:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[BP]], i64 24, i1 false) +// O0-NEXT: [[WIDE_PTR_PTR_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 0 +// O0-NEXT: [[WIDE_PTR_PTR31:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR30]], align 8 +// O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR31]], i64 5 +// O0-NEXT: [[WIDE_PTR_UB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 1 +// O0-NEXT: [[WIDE_PTR_UB33:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR32]], align 8 +// O0-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2 +// O0-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8 +// O0-NEXT: [[TMP20:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP21:%.*]] = icmp ule ptr [[TMP20]], [[WIDE_PTR_UB33]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP21]], label [[CONT37:%.*]], label [[TRAP36:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap36: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont37: -// O0-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP18]], align 4 -// O0-NEXT: ret i32 [[TMP21]] +// O0-NEXT: [[TMP22:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP20]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP22]], label [[CONT39:%.*]], label [[TRAP38:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap38: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont39: +// O0-NEXT: [[TMP23:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB35]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP23]], label [[CONT41:%.*]], label [[TRAP40:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap40: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont41: +// O0-NEXT: [[TMP24:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// O0-NEXT: ret i32 [[TMP24]] // // O2-LABEL: @main( // O2-NEXT: entry: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// O2-NEXT: unreachable +// O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/length-check-bound-check-removal.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/length-check-bound-check-removal.c index 8a8b032436764..e33df2b9b6c85 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/length-check-bound-check-removal.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/length-check-bound-check-removal.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 - // RUN: %clang_cc1 -O2 -fbounds-safety -triple x86_64 -emit-llvm %s -o - | FileCheck %s // #include @@ -17,15 +16,15 @@ void use(int *, int); // CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 8, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 2 -// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT11:%.*]] -// CHECK: cont11: +// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT13:%.*]] +// CHECK: cont13: // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA9:![0-9]+]] // CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA10:![0-9]+]] // CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH]], i32 noundef [[TMP2]]) #[[ATTR3:[0-9]+]] // CHECK-NEXT: br label [[CLEANUP]] // CHECK: cleanup: -// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT11]] ], [ -1, [[ENTRY:%.*]] ] +// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT13]] ], [ -1, [[ENTRY:%.*]] ] // CHECK-NEXT: ret i32 [[RETVAL_0]] // int access1(S *p) { @@ -47,30 +46,29 @@ int access1(S *p) { // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP0]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[IDX_EXT]] // CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 2 -// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT11:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[CONT25:%.*]] // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META11:![0-9]+]] // CHECK-NEXT: unreachable, !annotation [[META11]] -// CHECK: cont11: +// CHECK: cont25: // CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA10]] // CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH]], i32 noundef [[TMP2]]) #[[ATTR3]] -// CHECK-NEXT: [[BOUND_PTR_ARITH14:%.*]] = getelementptr i8, ptr [[TMP1]], i64 8 -// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[ADD_PTR]], !annotation [[META12:![0-9]+]] -// CHECK-NEXT: [[TMP4:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[TMP1]], !annotation [[META13:![0-9]+]] -// CHECK-NEXT: [[OR_COND35:%.*]] = and i1 [[TMP3]], [[TMP4]], !annotation [[META13]] -// CHECK-NEXT: br i1 [[OR_COND35]], label [[CONT22:%.*]], label [[TRAP:%.*]], !prof [[PROF14:![0-9]+]], !annotation [[META12]] -// CHECK: cont22: -// CHECK-NEXT: [[DOTNOT39:%.*]] = icmp eq ptr [[BOUND_PTR_ARITH14]], null, !annotation [[META15:![0-9]+]] -// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH14]], [[ADD_PTR]], !annotation [[META12]] -// CHECK-NEXT: [[OR_COND40:%.*]] = select i1 [[DOTNOT39]], i1 true, i1 [[TMP5]], !annotation [[META12]] -// CHECK-NEXT: br i1 [[OR_COND40]], label [[CONT32:%.*]], label [[TRAP]], !prof [[PROF16:![0-9]+]], !annotation [[META15]] -// CHECK: cont32: -// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, !tbaa [[TBAA10]] -// CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH14]], i32 noundef [[TMP6]]) #[[ATTR3]] +// CHECK-NEXT: [[BOUND_PTR_ARITH16:%.*]] = getelementptr i8, ptr [[TMP1]], i64 8 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, !tbaa [[TBAA10]] +// CHECK-NEXT: [[DOTNOT47:%.*]] = icmp eq ptr [[BOUND_PTR_ARITH16]], null, !annotation [[META12:![0-9]+]] +// CHECK-NEXT: br i1 [[DOTNOT47]], label [[CONT36:%.*]], label [[BOUNDSCHECK_NOTNULL33:%.*]], !annotation [[META12]] +// CHECK: boundscheck.notnull33: +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP1]], i64 12, !annotation [[META13:![0-9]+]] +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[ADD_PTR]], !annotation [[META13]] +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[BOUND_PTR_ARITH16]], [[TMP4]], !annotation [[META13]] +// CHECK-NEXT: [[OR_COND43:%.*]] = and i1 [[TMP5]], [[TMP6]], !annotation [[META13]] +// CHECK-NEXT: br i1 [[OR_COND43]], label [[CONT36]], label [[TRAP:%.*]], !prof [[PROF14:![0-9]+]], !annotation [[META13]] +// CHECK: cont36: +// CHECK-NEXT: tail call void @use(ptr noundef [[BOUND_PTR_ARITH16]], i32 noundef [[TMP3]]) #[[ATTR3]] // CHECK-NEXT: br label [[CLEANUP]] // CHECK: cleanup: -// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT32]] ], [ -1, [[ENTRY:%.*]] ] +// CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[CONT36]] ], [ -1, [[ENTRY:%.*]] ] // CHECK-NEXT: ret i32 [[RETVAL_0]] // int access2(S *p) { diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript-deref.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript-deref.c index 713f084952103..03b093219315e 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript-deref.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript-deref.c @@ -44,25 +44,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int arr[10]; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript.c index 207a4d19c4e32..7fcc9462dd4d6 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-array-subscript.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s @@ -10,16 +9,19 @@ // O2-NEXT: entry: // O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR:%.*]], i64 4 // O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 40 -// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} -// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} -// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARR]], i64 44, {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[UPPER]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // O2: trap: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// O2: cont1: -// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} -// O2-NEXT: ret i32 [[TMP2]] +// O2: cont2: +// O2-NEXT: [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} +// O2-NEXT: ret i32 [[TMP4]] // // O0-LABEL: @foo( // O0-NEXT: entry: @@ -46,22 +48,29 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP6:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP4]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP6]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -// O0-NEXT: store i32 [[TMP6]], ptr [[I]], align 4 -// O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4 -// O0-NEXT: ret i32 [[TMP7]] +// O0-NEXT: [[TMP7:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP7]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: [[TMP8:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// O0-NEXT: store i32 [[TMP8]], ptr [[I]], align 4 +// O0-NEXT: [[TMP9:%.*]] = load i32, ptr [[I]], align 4 +// O0-NEXT: ret i32 [[TMP9]] // int foo(int * arr) { int * bidi_arr = arr; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-dependent-count-ptr.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-dependent-count-ptr.c index 891160bf3f8ff..e61a57dae46a6 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-dependent-count-ptr.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/oob-dependent-count-ptr.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=O0 %s // RUN: %clang_cc1 -O2 -triple arm64e -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=O2 %s // RUN: %clang_cc1 -O0 -triple arm64e -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=O0 %s @@ -28,40 +27,50 @@ // O0-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8 // O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// O0-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 5 +// O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 5 // O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[TMP6]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP7:%.*]] = icmp ule ptr [[TMP6]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[TMP6]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP6]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: store i32 [[TMP0]], ptr [[TMP6]], align 4 +// O0-NEXT: [[TMP9:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: store i32 [[TMP0]], ptr [[ARRAYIDX]], align 4 // O0-NEXT: ret void // // O2-LABEL: @foo( // O2-NEXT: entry: // O2-NEXT: [[IDX_EXT:%.*]] = sext i32 [[LEN:%.*]] to i64 // O2-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[BUF:%.*]], i64 [[IDX_EXT]] -// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BUF]], i64 20 -// O2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// O2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[TMP0]], [[BUF]], {{!annotation ![0-9]+}} +// O2-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[BUF]], i64 20 +// O2-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BUF]], i64 24, {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP2:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP0]], {{!annotation ![0-9]+}} // O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP1]], {{!annotation ![0-9]+}} -// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O2-NEXT: [[TMP3:%.*]] = icmp uge ptr [[ARRAYIDX]], [[BUF]], {{!annotation ![0-9]+}} +// O2-NEXT: [[OR_COND3:%.*]] = and i1 [[TMP3]], [[OR_COND]], {{!annotation ![0-9]+}} +// O2-NEXT: br i1 [[OR_COND3]], label [[CONT2:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], {{!annotation ![0-9]+}} // O2: trap: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// O2: cont1: -// O2-NEXT: store i32 [[LEN]], ptr [[TMP0]], align 4, {{!tbaa ![0-9]+}} +// O2: cont2: +// O2-NEXT: store i32 [[LEN]], ptr [[ARRAYIDX]], align 4, {{!tbaa ![0-9]+}} // O2-NEXT: ret void // void foo(int *__counted_by(len) buf, int len) { diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound-ok.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound-ok.c index 00f1a999c2eaa..e16979c8eb210 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound-ok.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound-ok.c @@ -63,20 +63,27 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP21:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP22:%.*]] = icmp ule ptr [[TMP21]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP22]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP23:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP21]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP23]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap3: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont4: -// O0-NEXT: [[TMP23:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// O0-NEXT: ret i32 [[TMP23]] +// O0-NEXT: [[TMP24:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP24]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap5: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont6: +// O0-NEXT: [[TMP25:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP25]] // // O2-LABEL: @main( // O2-NEXT: entry: diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound.c index dcac06d8af2c1..ed9ca340f2d6e 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-compound.c @@ -43,25 +43,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int arr[4]; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec-ok.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec-ok.c index 2da353f01cb2d..0e6c54ff93002 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec-ok.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec-ok.c @@ -51,20 +51,27 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// O0-NEXT: ret i32 [[TMP15]] +// O0-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP16]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: [[TMP17:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP17]] // int foo(int * a) { int *p = a; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec.c index f71f61368d6dd..654ad5420c763 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postdec.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s // RUN: %clang_cc1 -triple x86_64 -O0 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -triple x86_64 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s @@ -8,18 +7,8 @@ // O2-LABEL: @foo( // O2-NEXT: entry: -// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 4 -// O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 -// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} -// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// O2: trap: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// O2: cont1: -// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} -// O2-NEXT: ret i32 [[TMP2]] // // O0-LABEL: @foo( // O0-NEXT: entry: @@ -61,20 +50,27 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// O0-NEXT: ret i32 [[TMP15]] +// O0-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP16]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: [[TMP17:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP17]] // int foo(int* a) { int *p = a; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc-ok.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc-ok.c index 0f991a96365a3..30aec87ddcbef 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc-ok.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc-ok.c @@ -51,20 +51,27 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// O0-NEXT: unreachable +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// O0-NEXT: ret i32 [[TMP15]] +// O0-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP16]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: [[TMP17:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP17]] // int foo(int* a) { int *p = a; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc.c index 73711acf37eb9..7898ac3629e9f 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-postinc.c @@ -46,25 +46,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int a[1] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec-self.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec-self.c index e6e7b06d5bc5e..911e460dc1109 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec-self.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec-self.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-O0 %s @@ -46,37 +45,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: -// CHECK-O2-NEXT: [[A:%.*]] = alloca [1 x i32], align 4 -// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[A]]) #[[ATTR3:[0-9]+]] -// CHECK-O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4 -// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 -// CHECK-O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK-O2: trap: -// CHECK-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} +// CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK-O2: cont1: -// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[A]]) #[[ATTR3]] -// CHECK-O2-NEXT: ret i32 undef // int main() { int a[1] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec.c index 4fdccc0eb0763..0d6bf06904f6d 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-predec.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck --check-prefixes O0 %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck --check-prefixes O2 %s @@ -8,18 +7,8 @@ // O2-LABEL: @foo( // O2-NEXT: entry: -// O2-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 4 -// O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i8, ptr [[A]], i64 -4 -// O2-NEXT: [[TMP0:%.*]] = icmp ult ptr [[BOUND_PTR_ARITH]], [[UPPER]], {{!annotation ![0-9]+}} -// O2-NEXT: [[TMP1:%.*]] = icmp uge ptr [[BOUND_PTR_ARITH]], [[A]], {{!annotation ![0-9]+}} -// O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// O2-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// O2: trap: // O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // O2-NEXT: unreachable, {{!annotation ![0-9]+}} -// O2: cont1: -// O2-NEXT: [[TMP2:%.*]] = load i32, ptr [[BOUND_PTR_ARITH]], align 4, {{!tbaa ![0-9]+}} -// O2-NEXT: ret i32 [[TMP2]] // // O0-LABEL: @foo( // O0-NEXT: entry: @@ -61,20 +50,27 @@ // O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// O0-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // O0: trap: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont: -// O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// O0-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP13]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP15]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // O0: trap1: // O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} // O0-NEXT: unreachable, {{!annotation ![0-9]+}} // O0: cont2: -// O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// O0-NEXT: ret i32 [[TMP15]] +// O0-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// O0-NEXT: br i1 [[TMP16]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// O0: trap3: +// O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// O0: cont4: +// O0-NEXT: [[TMP17:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// O0-NEXT: ret i32 [[TMP17]] // int foo(int * a) { int *p = a; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc-self.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc-self.c index a54760a8cc679..89146f6890c87 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc-self.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc-self.c @@ -46,25 +46,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int a[1] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc.c index 36ecb04827b94..120072e557f74 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-preinc.c @@ -46,25 +46,32 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP14:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP14]] +// CHECK-O0-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP15]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP16:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP16]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int main() { int a[1] = {0}; diff --git a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-prepost.c b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-prepost.c index b9c92cf21de45..c6dbd81ae5d6a 100644 --- a/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-prepost.c +++ b/clang/test/BoundsSafety/CodeGen/runtime-checks/ptr-arith-prepost.c @@ -61,20 +61,27 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP21:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP21:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP22:%.*]] = icmp ule ptr [[TMP21]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP22]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP22:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP22]], label [[CONT4:%.*]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP23:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP21]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP23]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont4: -// CHECK-O0-NEXT: [[TMP23:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP23]] +// CHECK-O0-NEXT: [[TMP24:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP24]], label [[CONT6:%.*]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap5: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont6: +// CHECK-O0-NEXT: [[TMP25:%.*]] = load i32, ptr [[WIDE_PTR_PTR]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP25]] // // CHECK-O2-LABEL: @main( // CHECK-O2-NEXT: entry: diff --git a/clang/test/BoundsSafety/CodeGen/single-null-O2.c b/clang/test/BoundsSafety/CodeGen/single-null-O2.c index 11fb350fd3384..390d254481cfa 100644 --- a/clang/test/BoundsSafety/CodeGen/single-null-O2.c +++ b/clang/test/BoundsSafety/CodeGen/single-null-O2.c @@ -20,6 +20,19 @@ int TestOK() { // FIXME // CHECK-O2-LABEL: @TestTrap( // CHECK-O2-NEXT: entry: +// CHECK-O2-NEXT: [[P:%.*]] = alloca i8, align 1 +// CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr nonnull [[P]]) #[[ATTR4:[0-9]+]] +// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 1 +// CHECK-O2-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P]], i64 4, !annotation [[META2:![0-9]+]] +// CHECK-O2-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[TMP0]], !annotation [[META2]] +// CHECK-O2-NEXT: [[TMP3:%.*]] = icmp ule ptr [[P]], [[TMP1]], !annotation [[META2]] +// CHECK-O2-NEXT: [[OR_COND:%.*]] = and i1 [[TMP2]], [[TMP3]], !annotation [[META2]] +// CHECK-O2-NEXT: br i1 [[OR_COND]], label [[CONT30:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// CHECK-O2: trap: +// CHECK-O2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5:[0-9]+]], !annotation [[META4:![0-9]+]] +// CHECK-O2-NEXT: unreachable, !annotation [[META4]] +// CHECK-O2: cont30: +// CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr nonnull [[P]]) #[[ATTR4]] // CHECK-O2-NEXT: ret void // void TestTrap() { diff --git a/clang/test/BoundsSafety/CodeGen/single-null.c b/clang/test/BoundsSafety/CodeGen/single-null.c index 1a65f3cdc8f49..73ee5e1812d0f 100644 --- a/clang/test/BoundsSafety/CodeGen/single-null.c +++ b/clang/test/BoundsSafety/CodeGen/single-null.c @@ -15,12 +15,12 @@ // CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK-O0-NEXT: store i32 0, ptr [[LEN]], align 4 -// CHECK-O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4 +// CHECK-O0-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN]], align 4, {{!annotation ![0-9]+}} // CHECK-O0-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0, {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: // CHECK-O0-NEXT: store ptr null, ptr [[DCP]], align 8 // CHECK-O0-NEXT: [[TMP1:%.*]] = load ptr, ptr [[DCP]], align 8 @@ -40,20 +40,27 @@ // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-O0-NEXT: [[TMP6:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT6:%.*]], {{!annotation ![0-9]+}} // CHECK-O0: boundscheck.notnull: -// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT4]], label [[TRAP3:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT6]], label [[TRAP5:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap5: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont6: // CHECK-O0-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TP]], align 8 // CHECK-O0-NEXT: ret i32 0 // diff --git a/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call-O2.c b/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call-O2.c index 7799147f91326..f0cc49639ad52 100644 --- a/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call-O2.c +++ b/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 - // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s @@ -167,20 +166,20 @@ void caller_9(int *__sized_by(*len) *out, int *len){ // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA8]] // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[CMP_NOT90:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] -// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT90]], i1 false, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT172:%.*]] = icmp slt i32 [[TMP1]], 0, !annotation [[META3]] +// CHECK-NEXT: [[CMP_NOT:%.*]] = select i1 [[DOTNOT]], i1 [[CMP_NOT172]], i1 false, !annotation [[META3]] // CHECK-NEXT: br i1 [[CMP_NOT]], label [[TRAP:%.*]], label [[LAND_RHS:%.*]], !annotation [[META3]] // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR6]], !annotation [[META16:![0-9]+]] // CHECK-NEXT: unreachable, !annotation [[META16]] // CHECK: land.rhs: -// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT67:%.*]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[DOTNOT]], label [[LOR_RHS:%.*]], label [[CONT146:%.*]], !annotation [[META3]] // CHECK: lor.rhs: -// CHECK-NEXT: [[CMP61:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] -// CHECK-NEXT: [[CMP64:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] -// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP64]], [[CMP61]] -// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT67]], label [[TRAP]], !prof [[PROF13]], !annotation [[META3]] -// CHECK: cont67: +// CHECK-NEXT: [[CMP63:%.*]] = icmp sge i32 [[TMP1]], [[LEN]], !annotation [[META3]] +// CHECK-NEXT: [[CMP66:%.*]] = icmp sgt i32 [[LEN]], -1, !annotation [[META3]] +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = and i1 [[CMP66]], [[CMP63]] +// CHECK-NEXT: br i1 [[SPEC_SELECT]], label [[CONT146]], label [[TRAP]], !prof [[PROF13]], !annotation [[META3]] +// CHECK: cont146: // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]) #[[ATTR5]] // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[COUNT]]) #[[ATTR5]] // CHECK-NEXT: ret ptr [[TMP0]] @@ -209,5 +208,5 @@ int *__sized_by_or_null(len) caller_10(int len) { // CHECK: [[PROF13]] = !{!"branch_weights", i32 1048575, i32 1} // CHECK: [[PROF14]] = !{!"branch_weights", i32 2097151, i32 1} // CHECK: [[META15]] = !{!"bounds-safety-zero-init"} -// CHECK: [[META16]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} +// CHECK: [[META16]] = !{!"bounds-safety-check-ptr-le-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound", !"bounds-safety-generic"} //. diff --git a/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call.c b/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call.c index 2c717054d57ee..8f1d01695c90a 100644 --- a/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call.c +++ b/clang/test/BoundsSafety/CodeGen/sized_by_or_null_call.c @@ -1,6 +1,5 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -Wno-bounds-safety-init-list -emit-llvm %s -o - | FileCheck %s @@ -10,12 +9,12 @@ void foo(int *__sized_by_or_null(len) p, int len); // CHECK-LABEL: define dso_local void @caller_1( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2:![0-9]+]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: br i1 true, label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2:![0-9]+]], !annotation [[META3:![0-9]+]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 2) // CHECK-NEXT: ret void // @@ -25,12 +24,12 @@ void caller_1() { // CHECK-LABEL: define dso_local void @caller_2( // CHECK-SAME: ) #[[ATTR0]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: br i1 true, label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @foo(ptr noundef null, i32 noundef 0) // CHECK-NEXT: ret void // @@ -40,7 +39,7 @@ void caller_2() { // CHECK-LABEL: define dso_local void @caller_3( // CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -58,9 +57,9 @@ void caller_2() { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP2]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull: +// CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META4:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP2]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL]]: // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDX_EXT]] // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 @@ -69,133 +68,133 @@ void caller_2() { // CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP4]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] -// CHECK: boundscheck.null: +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr null, ptr [[TMP6]], align 8 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: store ptr null, ptr [[TMP7]], align 8 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr null, ptr [[TMP8]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] -// CHECK: boundscheck.cont: +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: // CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] -// CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] -// CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP13]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP15]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP17]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP18]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs67: -// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] -// CHECK: lor.end: -// CHECK-NEXT: [[TMP20:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP19]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.end70: -// CHECK-NEXT: [[TMP21:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP20]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP21]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP10]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END70:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label %[[LAND_RHS:.*]], label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label %[[LOR_RHS:.*]], label %[[LOR_END:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP9]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP13]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP15]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP17]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP18]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP65]], label %[[LAND_RHS67:.*]], label %[[LAND_END:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS67]]: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP9]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META3]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, %[[LOR_RHS]] ], [ [[CMP68]], %[[LAND_RHS67]] ] +// CHECK-NEXT: br label %[[LOR_END]], !annotation [[META3]] +// CHECK: [[LOR_END]]: +// CHECK-NEXT: [[TMP20:%.*]] = phi i1 [ true, %[[LAND_RHS]] ], [ [[TMP19]], %[[LAND_END]] ] +// CHECK-NEXT: br label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_END70]]: +// CHECK-NEXT: [[TMP21:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[BOUNDSCHECK_CONT]] ], [ [[TMP20]], %[[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP21]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 @@ -212,7 +211,7 @@ void caller_3(int *__sized_by_or_null(len) p, int len) { // CHECK-LABEL: define dso_local void @caller_4( // CHECK-SAME: ) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -224,11 +223,11 @@ void caller_3(int *__sized_by_or_null(len) p, int len) { // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 -// CHECK-NEXT: br i1 false, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: br i1 false, label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 @@ -246,7 +245,7 @@ void caller_4() { // CHECK-LABEL: define dso_local void @caller_5( // CHECK-SAME: ) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -258,11 +257,11 @@ void caller_4() { // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[I]], ptr [[TMP3]], align 8 -// CHECK-NEXT: br i1 true, label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: br i1 true, label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 @@ -280,7 +279,7 @@ void caller_5() { // CHECK-LABEL: define dso_local void @caller_6( // CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -307,122 +306,122 @@ void caller_5() { // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 // CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] -// CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] -// CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP13]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs67: -// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] -// CHECK: lor.end: -// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP15]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.end70: -// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP16]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP17]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP6]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END70:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label %[[LAND_RHS:.*]], label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label %[[LOR_RHS:.*]], label %[[LOR_END:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP5]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP8]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP10]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP13]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP65]], label %[[LAND_RHS67:.*]], label %[[LAND_END:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS67]]: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP5]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META3]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, %[[LOR_RHS]] ], [ [[CMP68]], %[[LAND_RHS67]] ] +// CHECK-NEXT: br label %[[LOR_END]], !annotation [[META3]] +// CHECK: [[LOR_END]]: +// CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ true, %[[LAND_RHS]] ], [ [[TMP15]], %[[LAND_END]] ] +// CHECK-NEXT: br label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_END70]]: +// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[TMP16]], %[[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP17]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 @@ -439,7 +438,7 @@ void caller_6(int *__sized_by(len) p, int len) { // CHECK-LABEL: define dso_local void @caller_7( // CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -457,122 +456,122 @@ void caller_6(int *__sized_by(len) p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[P]], i64 24, i1 false) // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END70:%.*]], !annotation [[META2]] -// CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] -// CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP4]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP65]], label [[LAND_RHS67:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs67: -// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP68]], [[LAND_RHS67]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] -// CHECK: lor.end: -// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP10]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END70]], !annotation [[META2]] -// CHECK: land.end70: -// CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP11]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP2]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB4:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB4]], ptr [[TMP1]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END70:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB13]], ptr [[TMP2]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR15:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB19:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR18]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP20]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP27]], label %[[LAND_RHS:.*]], label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR30]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label %[[LOR_RHS:.*]], label %[[LOR_END:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB38]], ptr [[TMP3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR40:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR39]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB44:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR43]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR40]], ptr [[TMP4]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB44]], ptr [[TMP6]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR54]], ptr [[TMP7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB56]], ptr [[TMP8]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB58]], ptr [[TMP9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR46]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[CMP65:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP65]], label %[[LAND_RHS67:.*]], label %[[LAND_END:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS67]]: +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i32 0, [[TMP0]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META3]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, %[[LOR_RHS]] ], [ [[CMP68]], %[[LAND_RHS67]] ] +// CHECK-NEXT: br label %[[LOR_END]], !annotation [[META3]] +// CHECK: [[LOR_END]]: +// CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ true, %[[LAND_RHS]] ], [ [[TMP10]], %[[LAND_END]] ] +// CHECK-NEXT: br label %[[LAND_END70]], !annotation [[META3]] +// CHECK: [[LAND_END70]]: +// CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[TMP11]], %[[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP71]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP71]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR73:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR72]], align 8 @@ -589,7 +588,7 @@ void caller_7(int *__bidi_indexable p, int len) { // CHECK-LABEL: define dso_local void @caller_8( // CHECK-SAME: ptr noundef [[P:%.*]], i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -600,100 +599,100 @@ void caller_7(int *__bidi_indexable p, int len) { // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END36:%.*]], !annotation [[META2]] -// CHECK: land.lhs.true: -// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP13]], label [[LAND_RHS:%.*]], label [[LAND_END36]], !annotation [[META2]] -// CHECK: land.rhs: -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] -// CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[UPPER16:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META2]] -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[UPPER16]], ptr [[TMP11]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB18]], ptr [[TMP13]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR20]], ptr [[TMP14]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP15]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB24]], ptr [[TMP16]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR26]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[CMP31:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP31]], label [[LAND_RHS33:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs33: -// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP34]], [[LAND_RHS33]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] -// CHECK: lor.end: -// CHECK-NEXT: [[TMP18:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP17]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END36]], !annotation [[META2]] -// CHECK: land.end36: -// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[TMP18]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP19]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont: +// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP3]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB2:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR1]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_PTR]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END36:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP6]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP8]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB6]], ptr [[TMP9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR8:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR7]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB12:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP13:%.*]] = icmp ule ptr [[WIDE_PTR_PTR8]], [[TMP0]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP13]], label %[[LAND_RHS:.*]], label %[[LAND_END36]], !annotation [[META3]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP0]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label %[[LOR_RHS:.*]], label %[[LOR_END:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[UPPER16:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1, !annotation [[META3]] +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[UPPER16]], ptr [[TMP11]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP12]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB18]], ptr [[TMP13]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR20]], ptr [[TMP14]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB22]], ptr [[TMP15]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB24]], ptr [[TMP16]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR26]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP0]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[CMP31:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP31]], label %[[LAND_RHS33:.*]], label %[[LAND_END:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS33]]: +// CHECK-NEXT: [[CMP34:%.*]] = icmp sle i32 0, [[TMP1]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META3]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, %[[LOR_RHS]] ], [ [[CMP34]], %[[LAND_RHS33]] ] +// CHECK-NEXT: br label %[[LOR_END]], !annotation [[META3]] +// CHECK: [[LOR_END]]: +// CHECK-NEXT: [[TMP18:%.*]] = phi i1 [ true, %[[LAND_RHS]] ], [ [[TMP17]], %[[LAND_END]] ] +// CHECK-NEXT: br label %[[LAND_END36]], !annotation [[META3]] +// CHECK: [[LAND_END36]]: +// CHECK-NEXT: [[TMP19:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[TMP18]], %[[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP19]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT]]: // CHECK-NEXT: call void @foo(ptr noundef [[TMP0]], i32 noundef [[TMP1]]) // CHECK-NEXT: ret void // @@ -705,7 +704,7 @@ void bar(int *__sized_by(*len) *out, int *len); // CHECK-LABEL: define dso_local void @caller_9( // CHECK-SAME: ptr noundef [[OUT:%.*]], ptr noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[OUT]], ptr [[OUT_ADDR]], align 8 @@ -721,28 +720,37 @@ void caller_9(int *__sized_by(*len) *out, int *len){ // CHECK-LABEL: define dso_local ptr @caller_10( // CHECK-SAME: i32 noundef [[LEN:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: entry: +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 // CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 -// CHECK-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP17:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP29:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP23:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP30:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP44:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[AGG_TEMP51:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP72:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP79:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP54:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP55:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP76:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP95:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP101:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP104:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP114:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP124:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP127:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP128:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP154:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: store i32 [[LEN]], ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META4:![0-9]+]] -// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META4]] +// CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4, !annotation [[META5:![0-9]+]] +// CHECK-NEXT: store ptr null, ptr [[P]], align 8, !annotation [[META5]] // CHECK-NEXT: [[TMP0:%.*]] = getelementptr ptr, ptr [[P]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[P]], ptr [[TMP1]], align 8 @@ -764,187 +772,283 @@ void caller_9(int *__sized_by(*len) *out, int *len){ // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP2]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP8]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP9:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], !annotation [[META5:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP9]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META5]] -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] -// CHECK-NEXT: unreachable, !annotation [[META5]] -// CHECK: cont: -// CHECK-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META6:![0-9]+]] -// CHECK-NEXT: br i1 [[TMP10]], label [[CONT4]], label [[TRAP3:%.*]], !annotation [[META6]] -// CHECK: trap3: +// CHECK-NEXT: [[TMP8:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP8]], label %[[BOUNDSCHECK_NOTNULL:.*]], label %[[CONT6:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL]]: +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr ptr, ptr [[WIDE_PTR_PTR]], i64 1, !annotation [[META6:![0-9]+]] +// CHECK-NEXT: [[TMP10:%.*]] = icmp ule ptr [[TMP9]], [[WIDE_PTR_UB]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP10]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF2]], !annotation [[META6]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[TMP11:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP9]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP11]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF2]], !annotation [[META6]] +// CHECK: [[TRAP3]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] +// CHECK-NEXT: unreachable, !annotation [[META6]] +// CHECK: [[CONT4]]: +// CHECK-NEXT: [[TMP12:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META7:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT6]], label %[[TRAP5:.*]], !prof [[PROF2]], !annotation [[META7]] +// CHECK: [[TRAP5]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT6]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = icmp ne ptr [[WIDE_PTR_PTR9]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP13]], label %[[BOUNDSCHECK_NOTNULL14:.*]], label %[[CONT20:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL14]]: +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR9]], i64 1, !annotation [[META6]] +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[TMP14]], [[WIDE_PTR_UB11]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT16:.*]], label %[[TRAP15:.*]], !prof [[PROF2]], !annotation [[META6]] +// CHECK: [[TRAP15]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] // CHECK-NEXT: unreachable, !annotation [[META6]] -// CHECK: cont4: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[AGG_TEMP1]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR7]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL12:%.*]], label [[CONT16:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull12: -// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_UB9]], !annotation [[META5]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT14:%.*]], label [[TRAP13:%.*]], !annotation [[META5]] -// CHECK: trap13: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META5]] -// CHECK-NEXT: unreachable, !annotation [[META5]] -// CHECK: cont14: -// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR7]], [[WIDE_PTR_LB11]], !annotation [[META6]] -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT16]], label [[TRAP15:%.*]], !annotation [[META6]] -// CHECK: trap15: +// CHECK: [[CONT16]]: +// CHECK-NEXT: [[TMP16:%.*]] = icmp ule ptr [[WIDE_PTR_PTR9]], [[TMP14]], !annotation [[META6]] +// CHECK-NEXT: br i1 [[TMP16]], label %[[CONT18:.*]], label %[[TRAP17:.*]], !prof [[PROF2]], !annotation [[META6]] +// CHECK: [[TRAP17]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META6]] // CHECK-NEXT: unreachable, !annotation [[META6]] -// CHECK: cont16: -// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR7]]) -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP16:%.*]] = icmp ne ptr [[TMP14]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP16]], label [[BOUNDSCHECK_NOTNULL18:%.*]], label [[BOUNDSCHECK_NULL:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull18: -// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP15]] to i64 -// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP14]], i64 [[IDX_EXT]] -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP17]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP19]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT:%.*]] -// CHECK: boundscheck.null: -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP17]], i32 0, i32 2 -// CHECK-NEXT: store ptr null, ptr [[TMP22]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]] -// CHECK: boundscheck.cont: -// CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP19]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR21:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR20]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB23:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR22]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP19]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB25:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR24]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR21]], [[WIDE_PTR_UB28]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END69:%.*]], !annotation [[META2]] -// CHECK: land.lhs.true: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP29]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP29]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB31:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR30]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP32]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[CMP39:%.*]] = icmp ule ptr [[WIDE_PTR_LB31]], [[WIDE_PTR_PTR34]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP39]], label [[LAND_RHS:%.*]], label [[LAND_END69]], !annotation [[META2]] -// CHECK: land.rhs: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP40]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR42]], null, !annotation [[META2]] -// CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]], !annotation [[META2]] -// CHECK: lor.rhs: -// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP23]] to i64, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP47]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP47]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8, !annotation [[META2]] -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false), !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR53:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR52]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB55:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR54]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB57:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR56]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR53]], ptr [[TMP24]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_UB55]], ptr [[TMP25]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: store ptr [[WIDE_PTR_LB57]], ptr [[TMP26]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_PTR59:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR58]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_UB61:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR60]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, !annotation [[META2]] -// CHECK-NEXT: [[WIDE_PTR_LB63:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR62]], align 8, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB49]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR59]] to i64, !annotation [[META2]] -// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META2]] -// CHECK-NEXT: [[CMP64:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META2]] -// CHECK-NEXT: br i1 [[CMP64]], label [[LAND_RHS66:%.*]], label [[LAND_END:%.*]], !annotation [[META2]] -// CHECK: land.rhs66: -// CHECK-NEXT: [[CMP67:%.*]] = icmp sle i32 0, [[TMP23]], !annotation [[META2]] -// CHECK-NEXT: br label [[LAND_END]], !annotation [[META2]] -// CHECK: land.end: -// CHECK-NEXT: [[TMP27:%.*]] = phi i1 [ false, [[LOR_RHS]] ], [ [[CMP67]], [[LAND_RHS66]] ] -// CHECK-NEXT: br label [[LOR_END]], !annotation [[META2]] -// CHECK: lor.end: -// CHECK-NEXT: [[TMP28:%.*]] = phi i1 [ true, [[LAND_RHS]] ], [ [[TMP27]], [[LAND_END]] ] -// CHECK-NEXT: br label [[LAND_END69]], !annotation [[META2]] -// CHECK: land.end69: -// CHECK-NEXT: [[TMP29:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[BOUNDSCHECK_CONT]] ], [ [[TMP28]], [[LOR_END]] ], !annotation [[META2]] -// CHECK-NEXT: br i1 [[TMP29]], label [[CONT71:%.*]], label [[TRAP70:%.*]], !annotation [[META2]] -// CHECK: trap70: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META2]] -// CHECK-NEXT: unreachable, !annotation [[META2]] -// CHECK: cont71: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP72]], ptr align 8 [[AGG_TEMP17]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR74:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR73]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR75:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB76:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR75]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP72]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB78:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR77]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR74]], ptr [[P]], align 8 -// CHECK-NEXT: store i32 [[TMP23]], ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP30:%.*]] = load ptr, ptr [[P]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = load i32, ptr [[COUNT]], align 4 -// CHECK-NEXT: [[TMP32:%.*]] = icmp ne ptr [[TMP30]], null, !annotation [[META3]] -// CHECK-NEXT: br i1 [[TMP32]], label [[BOUNDSCHECK_NOTNULL80:%.*]], label [[BOUNDSCHECK_NULL83:%.*]], !annotation [[META3]] -// CHECK: boundscheck.notnull80: -// CHECK-NEXT: [[IDX_EXT81:%.*]] = sext i32 [[TMP31]] to i64 -// CHECK-NEXT: [[ADD_PTR82:%.*]] = getelementptr inbounds i8, ptr [[TMP30]], i64 [[IDX_EXT81]] -// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP33]], align 8 -// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[ADD_PTR82]], ptr [[TMP34]], align 8 -// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP35]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT84:%.*]] -// CHECK: boundscheck.null83: -// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 -// CHECK-NEXT: store ptr null, ptr [[TMP36]], align 8 -// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 -// CHECK-NEXT: store ptr null, ptr [[TMP37]], align 8 -// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 -// CHECK-NEXT: store ptr null, ptr [[TMP38]], align 8 -// CHECK-NEXT: br label [[BOUNDSCHECK_CONT84]] -// CHECK: boundscheck.cont84: -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR86:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR85]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB88:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR87]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP79]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB90:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR89]], align 8 -// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR86]] +// CHECK: [[CONT18]]: +// CHECK-NEXT: [[TMP17:%.*]] = icmp uge ptr [[WIDE_PTR_PTR9]], [[WIDE_PTR_LB13]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[TMP17]], label %[[CONT20]], label %[[TRAP19:.*]], !prof [[PROF2]], !annotation [[META7]] +// CHECK: [[TRAP19]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT20]]: +// CHECK-NEXT: call void @bar(ptr noundef [[WIDE_PTR_PTR]], ptr noundef [[WIDE_PTR_PTR9]]) +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP20:%.*]] = icmp ne ptr [[TMP18]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP20]], label %[[BOUNDSCHECK_NOTNULL22:.*]], label %[[BOUNDSCHECK_NULL:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL22]]: +// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP19]] to i64 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP18]], i64 [[IDX_EXT]] +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP23]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT:.*]] +// CHECK: [[BOUNDSCHECK_NULL]]: +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP21]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP26]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT]] +// CHECK: [[BOUNDSCHECK_CONT]]: +// CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP23]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR25:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR24]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB27:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR26]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP23]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB29:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR28]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP30]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP30]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR25]], [[WIDE_PTR_UB32]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END73:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP33]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB35:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR34]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR38:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR37]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB40:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR39]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB42:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR41]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP43:%.*]] = icmp ule ptr [[WIDE_PTR_LB35]], [[WIDE_PTR_PTR38]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP43]], label %[[LAND_RHS:.*]], label %[[LAND_END73]], !annotation [[META3]] +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP44]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP44]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[WIDE_PTR_PTR46]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL]], label %[[LOR_RHS:.*]], label %[[LOR_END:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS]]: +// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP27]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP51]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP51]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP55]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP55]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR57:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR56]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP55]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB59:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR58]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP55]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB61:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR60]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR57]], ptr [[TMP28]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB59]], ptr [[TMP29]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB61]], ptr [[TMP30]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR63:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR62]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR64:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB65:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR64]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR66:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP54]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB67:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR66]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB53]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR63]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], !annotation [[META3]] +// CHECK-NEXT: [[CMP68:%.*]] = icmp sle i64 [[CONV]], [[SUB_PTR_SUB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP68]], label %[[LAND_RHS70:.*]], label %[[LAND_END:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS70]]: +// CHECK-NEXT: [[CMP71:%.*]] = icmp sle i32 0, [[TMP27]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END]], !annotation [[META3]] +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP31:%.*]] = phi i1 [ false, %[[LOR_RHS]] ], [ [[CMP71]], %[[LAND_RHS70]] ] +// CHECK-NEXT: br label %[[LOR_END]], !annotation [[META3]] +// CHECK: [[LOR_END]]: +// CHECK-NEXT: [[TMP32:%.*]] = phi i1 [ true, %[[LAND_RHS]] ], [ [[TMP31]], %[[LAND_END]] ] +// CHECK-NEXT: br label %[[LAND_END73]], !annotation [[META3]] +// CHECK: [[LAND_END73]]: +// CHECK-NEXT: [[TMP33:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[BOUNDSCHECK_CONT]] ], [ [[TMP32]], %[[LOR_END]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP33]], label %[[CONT75:.*]], label %[[TRAP74:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP74]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT75]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP76]], ptr align 8 [[AGG_TEMP21]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR78:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR77]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR79:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB80:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR79]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR81:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB82:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR81]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR78]], ptr [[P]], align 8 +// CHECK-NEXT: store i32 [[TMP27]], ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[P]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load i32, ptr [[COUNT]], align 4 +// CHECK-NEXT: [[TMP36:%.*]] = icmp ne ptr [[TMP34]], null, !annotation [[META4]] +// CHECK-NEXT: br i1 [[TMP36]], label %[[BOUNDSCHECK_NOTNULL83:.*]], label %[[BOUNDSCHECK_NULL86:.*]], !annotation [[META4]] +// CHECK: [[BOUNDSCHECK_NOTNULL83]]: +// CHECK-NEXT: [[IDX_EXT84:%.*]] = sext i32 [[TMP35]] to i64 +// CHECK-NEXT: [[ADD_PTR85:%.*]] = getelementptr inbounds i8, ptr [[TMP34]], i64 [[IDX_EXT84]] +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[TMP34]], ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[ADD_PTR85]], ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP34]], ptr [[TMP39]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT87:.*]] +// CHECK: [[BOUNDSCHECK_NULL86]]: +// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr [[TMP40]], align 8 +// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr null, ptr [[TMP41]], align 8 +// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr null, ptr [[TMP42]], align 8 +// CHECK-NEXT: br label %[[BOUNDSCHECK_CONT87]] +// CHECK: [[BOUNDSCHECK_CONT87]]: +// CHECK-NEXT: [[TMP43:%.*]] = load i32, ptr [[LEN_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP88]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP88]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR90:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR89]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR91:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP88]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB92:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR91]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR93:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP88]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB94:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR93]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP95]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR96:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP95]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB97:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR96]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP98:%.*]] = icmp ule ptr [[WIDE_PTR_PTR90]], [[WIDE_PTR_UB97]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP98]], label %[[LAND_LHS_TRUE100:.*]], label %[[LAND_END151:.*]], !annotation [[META3]] +// CHECK: [[LAND_LHS_TRUE100]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP101]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP101]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB103:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR102]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP104]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR105:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP104]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR106:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR105]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR107:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP104]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB108:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR107]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR109:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP104]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB110:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR109]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[CMP111:%.*]] = icmp ule ptr [[WIDE_PTR_LB103]], [[WIDE_PTR_PTR106]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP111]], label %[[LAND_RHS113:.*]], label %[[LAND_END151]], !annotation [[META3]] +// CHECK: [[LAND_RHS113]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP114]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR115:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP114]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR116:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR115]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR117:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP114]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB118:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR117]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR119:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP114]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB120:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR119]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TOBOOL121:%.*]] = icmp ne ptr [[WIDE_PTR_PTR116]], null, !annotation [[META3]] +// CHECK-NEXT: br i1 [[TOBOOL121]], label %[[LOR_RHS122:.*]], label %[[LOR_END150:.*]], !annotation [[META3]] +// CHECK: [[LOR_RHS122]]: +// CHECK-NEXT: [[CONV123:%.*]] = sext i32 [[TMP43]] to i64, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP124]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR125:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP124]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB126:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR125]], align 8, !annotation [[META3]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP128]], ptr align 8 [[TMP]], i64 24, i1 false), !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR129:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP128]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR130:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR129]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR131:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP128]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB132:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR131]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR133:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP128]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB134:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR133]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR130]], ptr [[TMP44]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_UB132]], ptr [[TMP45]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: store ptr [[WIDE_PTR_LB134]], ptr [[TMP46]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR135:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 0, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_PTR136:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR135]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR137:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 1, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_UB138:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR137]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR139:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP127]], i32 0, i32 2, !annotation [[META3]] +// CHECK-NEXT: [[WIDE_PTR_LB140:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR139]], align 8, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_LHS_CAST141:%.*]] = ptrtoint ptr [[WIDE_PTR_UB126]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_RHS_CAST142:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR136]] to i64, !annotation [[META3]] +// CHECK-NEXT: [[SUB_PTR_SUB143:%.*]] = sub i64 [[SUB_PTR_LHS_CAST141]], [[SUB_PTR_RHS_CAST142]], !annotation [[META3]] +// CHECK-NEXT: [[CMP144:%.*]] = icmp sle i64 [[CONV123]], [[SUB_PTR_SUB143]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[CMP144]], label %[[LAND_RHS146:.*]], label %[[LAND_END149:.*]], !annotation [[META3]] +// CHECK: [[LAND_RHS146]]: +// CHECK-NEXT: [[CMP147:%.*]] = icmp sle i32 0, [[TMP43]], !annotation [[META3]] +// CHECK-NEXT: br label %[[LAND_END149]], !annotation [[META3]] +// CHECK: [[LAND_END149]]: +// CHECK-NEXT: [[TMP47:%.*]] = phi i1 [ false, %[[LOR_RHS122]] ], [ [[CMP147]], %[[LAND_RHS146]] ] +// CHECK-NEXT: br label %[[LOR_END150]], !annotation [[META3]] +// CHECK: [[LOR_END150]]: +// CHECK-NEXT: [[TMP48:%.*]] = phi i1 [ true, %[[LAND_RHS113]] ], [ [[TMP47]], %[[LAND_END149]] ] +// CHECK-NEXT: br label %[[LAND_END151]], !annotation [[META3]] +// CHECK: [[LAND_END151]]: +// CHECK-NEXT: [[TMP49:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE100]] ], [ false, %[[BOUNDSCHECK_CONT87]] ], [ [[TMP48]], %[[LOR_END150]] ], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP49]], label %[[CONT153:.*]], label %[[TRAP152:.*]], !prof [[PROF2]], !annotation [[META3]] +// CHECK: [[TRAP152]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] +// CHECK: [[CONT153]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP154]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR155:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP154]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR156:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR155]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR157:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP154]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB158:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR157]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR159:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP154]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB160:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR159]], align 8 +// CHECK-NEXT: ret ptr [[WIDE_PTR_PTR156]] // int *__sized_by_or_null(len) caller_10(int len) { int count; @@ -955,9 +1059,10 @@ int *__sized_by_or_null(len) caller_10(int len) { return p; } //. -// CHECK: [[META2]] = !{!"bounds-safety-generic"} -// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-neq-null"} -// CHECK: [[META4]] = !{!"bounds-safety-zero-init"} -// CHECK: [[META5]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} -// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[PROF2]] = !{!"branch_weights", i32 1048575, i32 1} +// CHECK: [[META3]] = !{!"bounds-safety-generic"} +// CHECK: [[META4]] = !{!"bounds-safety-check-ptr-neq-null"} +// CHECK: [[META5]] = !{!"bounds-safety-zero-init"} +// CHECK: [[META6]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[META7]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-O2.c b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-O2.c index e3d42603aaef4..ed2fb2313b647 100644 --- a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-O2.c +++ b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -7,19 +6,22 @@ // CHECK-LABEL: @indexable( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[PTR_COERCE0:%.*]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[PTR_COERCE0:%.*]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[PTR_COERCE0]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT2:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT3:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] // CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[PTR_COERCE1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT2]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} -// CHECK: cont2: -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP1]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT3]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP3]], 0 // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] // CHECK: terminated_by.loop_end: // CHECK-NEXT: ret ptr [[PTR_COERCE0]] @@ -35,21 +37,25 @@ int *__null_terminated indexable(int *__indexable ptr) { // CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_2_0_PTR_SROA_IDX]], align 8 // CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 16 // CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_PTR_SROA_IDX]], align 8, {{!tbaa ![0-9]+}} -// CHECK-NEXT: [[DOTNOT:%.*]] = icmp uge ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_3_0_COPYLOAD]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 [[TMP0]], i1 false, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF13:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_3_0_COPYLOAD]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof [[PROF6]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT8:%.*]] ], [ [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT9:%.*]] ], [ [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[CONT]] ] // CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT8]], !prof [[PROF6]], {{!annotation ![0-9]+}} -// CHECK: cont8: -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP1]], 0 +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT9]], !prof [[PROF6]], {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TERMINATED_BY_CUR_0]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP3]], 0 // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] // CHECK: terminated_by.loop_end: // CHECK-NEXT: ret ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]] @@ -60,19 +66,22 @@ int *__null_terminated bidi_indexable(int *__bidi_indexable ptr) { // CHECK-LABEL: @nested_indexable( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[PTR_COERCE0:%.*]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[PTR_COERCE0:%.*]], i64 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[PTR_COERCE1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[PTR_COERCE0]], [[TMP0]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP1]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[OR_COND]], label [[TERMINATED_BY_LOOP_COND:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT2:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[TERMINATED_BY_CUR_0:%.*]] = phi ptr [ [[TERMINATED_BY_ONE_PAST_CUR:%.*]], [[CONT3:%.*]] ], [ [[PTR_COERCE0]], [[ENTRY:%.*]] ] // CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR]] = getelementptr inbounds nuw i8, ptr [[TERMINATED_BY_CUR_0]], i64 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS_NOT:%.*]] = icmp ugt ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[PTR_COERCE1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT2]], !prof [[PROF6]], {{!annotation ![0-9]+}} -// CHECK: cont2: -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR_0]], align 8 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP1]], inttoptr (i64 -1 to ptr) +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS_NOT]], label [[TRAP]], label [[CONT3]], !prof [[PROF6]], {{!annotation ![0-9]+}} +// CHECK: cont3: +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR_0]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP3]], inttoptr (i64 -1 to ptr) // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_COND]] // CHECK: terminated_by.loop_end: // CHECK-NEXT: ret ptr [[PTR_COERCE0]] diff --git a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-trivial-O2.c b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-trivial-O2.c index 4eda5ca5ab4aa..47fdb7fa724c7 100644 --- a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-trivial-O2.c +++ b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable-trivial-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -14,7 +13,7 @@ static const struct { }; // CHECK-LABEL: @good( -// CHECK-NEXT: cont8.2: +// CHECK-NEXT: cont9.2: // CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @foo, i64 4) // const int *__terminated_by(3) good(void) { @@ -23,7 +22,7 @@ const int *__terminated_by(3) good(void) { } // CHECK-LABEL: @good_2( -// CHECK-NEXT: cont8.1: +// CHECK-NEXT: cont9.1: // CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @foo, i64 4) // const int *__terminated_by(2) good_2(void) { diff --git a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable.c b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable.c index 3875730293836..ecbf6e0d3ee94 100644 --- a/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable.c +++ b/clang/test/BoundsSafety/CodeGen/terminated-by-from-indexable.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -19,25 +18,32 @@ // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TERMINATED_BY_CUR]], align 8 // CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 -// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR1]], i64 1 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]] -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap2: +// CHECK-NEXT: [[TERMINATED_BY_CUR3:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR3]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap4: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont3: -// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TERMINATED_BY_CUR1]], align 4 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP3]], 0 +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont5: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TERMINATED_BY_CUR3]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP5]], 0 // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] // CHECK: terminated_by.loop_cont: // CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 @@ -59,13 +65,13 @@ int *__null_terminated indexable(int *__indexable ptr) { // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[TMP0:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP1]], align 8 @@ -75,25 +81,32 @@ int *__null_terminated indexable(int *__indexable ptr) { // CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR3]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT7:%.*]], label [[TRAP6:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap6: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont7: +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[WIDE_PTR_PTR3]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[TERMINATED_BY_CUR]], align 8 // CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR8:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 -// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR8]], i64 1 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB5]] -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT10:%.*]], label [[TRAP9:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap9: +// CHECK-NEXT: [[TERMINATED_BY_CUR10:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds i32, ptr [[TERMINATED_BY_CUR10]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT12:%.*]], label [[TRAP11:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap11: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont10: -// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TERMINATED_BY_CUR8]], align 4 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP4]], 0 +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont12: +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[TERMINATED_BY_CUR10]], align 4 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq i32 [[TMP6]], 0 // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] // CHECK: terminated_by.loop_cont: // CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 @@ -119,25 +132,32 @@ int *__null_terminated bidi_indexable(int *__bidi_indexable ptr) { // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr ptr, ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP3:%.*]] = icmp ule ptr [[TMP2]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: +// CHECK-NEXT: [[TMP4:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP2]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP4]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap1: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont2: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TERMINATED_BY_CUR]], align 8 // CHECK-NEXT: br label [[TERMINATED_BY_LOOP_COND:%.*]] // CHECK: terminated_by.loop_cond: -// CHECK-NEXT: [[TERMINATED_BY_CUR1:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8 -// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds ptr, ptr [[TERMINATED_BY_CUR1]], i64 1 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]] -// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT3:%.*]], label [[TRAP2:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap2: +// CHECK-NEXT: [[TERMINATED_BY_CUR3:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_ONE_PAST_CUR:%.*]] = getelementptr inbounds ptr, ptr [[TERMINATED_BY_CUR3]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TERMINATED_BY_CHECK_ACCESS:%.*]] = icmp ule ptr [[TERMINATED_BY_ONE_PAST_CUR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_ACCESS]], label [[CONT5:%.*]], label [[TRAP4:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap4: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-NEXT: unreachable -// CHECK: cont3: -// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR1]], align 8 -// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP3]], inttoptr (i64 -1 to ptr) +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont5: +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TERMINATED_BY_CUR3]], align 8 +// CHECK-NEXT: [[TERMINATED_BY_CHECK_TERMINATOR:%.*]] = icmp eq ptr [[TMP5]], inttoptr (i64 -1 to ptr) // CHECK-NEXT: br i1 [[TERMINATED_BY_CHECK_TERMINATOR]], label [[TERMINATED_BY_LOOP_END:%.*]], label [[TERMINATED_BY_LOOP_CONT:%.*]] // CHECK: terminated_by.loop_cont: // CHECK-NEXT: store ptr [[TERMINATED_BY_ONE_PAST_CUR]], ptr [[TERMINATED_BY_CUR]], align 8 diff --git a/clang/test/BoundsSafety/CodeGen/terminated-by-ptr-relaxed-casting.c b/clang/test/BoundsSafety/CodeGen/terminated-by-ptr-relaxed-casting.c index 794db108a5ee2..3877fec47395f 100644 --- a/clang/test/BoundsSafety/CodeGen/terminated-by-ptr-relaxed-casting.c +++ b/clang/test/BoundsSafety/CodeGen/terminated-by-ptr-relaxed-casting.c @@ -50,36 +50,43 @@ void bar(const char * __null_terminated * __single); // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null -// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT2:%.*]], +// CHECK-NEXT: [[TMP11:%.*]] = icmp ne ptr [[WIDE_PTR_PTR]], null, !annotation [[META2:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP11]], label [[BOUNDSCHECK_NOTNULL:%.*]], label [[CONT4:%.*]], !annotation [[META2]] // CHECK: boundscheck.notnull: -// CHECK-NEXT: [[TMP12:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]] -// CHECK-NEXT: br i1 [[TMP12]], label [[CONT:%.*]], label [[TRAP:%.*]] +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr ptr, ptr [[WIDE_PTR_PTR]], i64 1, !annotation [[META3:![0-9]+]] +// CHECK-NEXT: [[TMP13:%.*]] = icmp ule ptr [[TMP12]], [[WIDE_PTR_UB]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF4:![0-9]+]], !annotation [[META3]] // CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]] -// CHECK-NEXT: unreachable +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont: -// CHECK-NEXT: [[TMP13:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]] -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT2]], label [[TRAP1:%.*]] +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP12]], !annotation [[META3]] +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF4]], !annotation [[META3]] // CHECK: trap1: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]] -// CHECK-NEXT: unreachable +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META3]] +// CHECK-NEXT: unreachable, !annotation [[META3]] // CHECK: cont2: +// CHECK-NEXT: [[TMP15:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], !annotation [[META5:![0-9]+]] +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT4]], label [[TRAP3:%.*]], !prof [[PROF4]], !annotation [[META5]] +// CHECK: trap3: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META5]] +// CHECK-NEXT: unreachable, !annotation [[META5]] +// CHECK: cont4: // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[SPP]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[SPP]], align 8 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[NTPP]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[SPP]], align 8 -// CHECK-NEXT: store ptr [[TMP15]], ptr [[NTPP2]], align 8 // CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[SPP]], align 8 -// CHECK-NEXT: call void @bar(ptr noundef [[TMP16]]) +// CHECK-NEXT: store ptr [[TMP16]], ptr [[NTPP]], align 8 // CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[SPP]], align 8 -// CHECK-NEXT: call void @bar(ptr noundef [[TMP17]]) -// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[NTPP]], align 8 -// CHECK-NEXT: store ptr [[TMP18]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[NTPP2]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP18]]) // CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[SPP]], align 8 -// CHECK-NEXT: store ptr [[TMP19]], ptr [[NTPP3]], align 8 -// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: call void @bar(ptr noundef [[TMP19]]) +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[NTPP]], align 8 // CHECK-NEXT: store ptr [[TMP20]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP21]], ptr [[NTPP3]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[SPP]], align 8 +// CHECK-NEXT: store ptr [[TMP22]], ptr [[NTPP3]], align 8 // CHECK-NEXT: ret void // void test(const char * __single sp) { diff --git a/clang/test/BoundsSafety/CodeGen/trap-function-returns-O2.c b/clang/test/BoundsSafety/CodeGen/trap-function-returns-O2.c index 4abbf4260350a..08b1c9ee79e40 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-function-returns-O2.c +++ b/clang/test/BoundsSafety/CodeGen/trap-function-returns-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 - // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -ftrap-function=fb_trap -ftrap-function-returns -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=X86_64 #include @@ -10,19 +9,26 @@ // X86_64-NEXT: [[IDX_EXT:%.*]] = zext i32 [[COUNT]] to i64 // X86_64-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[BAR]], i64 [[IDX_EXT]] // X86_64-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[BAR]], i64 4 -// X86_64-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[ADD_PTR]], !annotation [[META2:![0-9]+]] -// X86_64-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// X86_64-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BAR]], i64 8, !annotation [[META2:![0-9]+]] +// X86_64-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[ADD_PTR]], !annotation [[META2]] +// X86_64-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] // X86_64: trap: // X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1:[0-9]+]], !annotation [[META2]] // X86_64-NEXT: br label [[CONT]], !annotation [[META2]] // X86_64: cont: -// X86_64-NEXT: [[DOTNOT:%.*]] = icmp ult ptr [[ARRAYIDX]], [[BAR]], !annotation [[META4:![0-9]+]] -// X86_64-NEXT: br i1 [[DOTNOT]], label [[TRAP1:%.*]], label [[CONT2:%.*]], !prof [[PROF5:![0-9]+]], !annotation [[META4]] +// X86_64-NEXT: [[DOTNOT5:%.*]] = icmp ugt ptr [[ARRAYIDX]], [[TMP0]], !annotation [[META2]] +// X86_64-NEXT: br i1 [[DOTNOT5]], label [[TRAP1:%.*]], label [[CONT2:%.*]], !prof [[PROF3]], !annotation [[META2]] // X86_64: trap1: -// X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META4]] -// X86_64-NEXT: br label [[CONT2]], !annotation [[META4]] +// X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META2]] +// X86_64-NEXT: br label [[CONT2]], !annotation [[META2]] // X86_64: cont2: -// X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA6:![0-9]+]] +// X86_64-NEXT: [[DOTNOT6:%.*]] = icmp ult ptr [[ARRAYIDX]], [[BAR]], !annotation [[META4:![0-9]+]] +// X86_64-NEXT: br i1 [[DOTNOT6]], label [[TRAP3:%.*]], label [[CONT4:%.*]], !prof [[PROF3]], !annotation [[META4]] +// X86_64: trap3: +// X86_64-NEXT: tail call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META4]] +// X86_64-NEXT: br label [[CONT4]], !annotation [[META4]] +// X86_64: cont4: +// X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA5:![0-9]+]] // X86_64-NEXT: ret i32 [[TMP1]] // int foo(int *__counted_by(count) bar, unsigned count) { diff --git a/clang/test/BoundsSafety/CodeGen/trap-function-returns.c b/clang/test/BoundsSafety/CodeGen/trap-function-returns.c index ae614d4d98f97..ca18bbc231c61 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-function-returns.c +++ b/clang/test/BoundsSafety/CodeGen/trap-function-returns.c @@ -1,11 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name TMP_ --version 3 - // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -ftrap-function=fb_trap -ftrap-function-returns -emit-llvm %s -o - | FileCheck %s --check-prefix=X86_64 #include -// X86_64-LABEL: define dso_local i32 @foo -// X86_64-SAME: (ptr noundef [[BAR:%.*]], i32 noundef [[COUNT:%.*]]) #[[ATTR0:[0-9]+]] { +// X86_64-LABEL: define dso_local i32 @foo( +// X86_64-SAME: ptr noundef [[BAR:%.*]], i32 noundef [[COUNT:%.*]]) #[[ATTR0:[0-9]+]] { // X86_64-NEXT: entry: // X86_64-NEXT: [[BAR_ADDR:%.*]] = alloca ptr, align 8 // X86_64-NEXT: [[COUNT_ADDR:%.*]] = alloca i32, align 4 @@ -24,30 +23,33 @@ // X86_64-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 // X86_64-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // X86_64-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// X86_64-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1 +// X86_64-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 1 // X86_64-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // X86_64-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // X86_64-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // X86_64-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// X86_64-NEXT: [[TMP6:%.*]] = icmp ult ptr [[TMP5]], [[WIDE_PTR_UB]], !annotation [[META2:![0-9]+]] -// X86_64-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !annotation [[META2]] +// X86_64-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, !annotation [[META2:![0-9]+]] +// X86_64-NEXT: [[TMP6:%.*]] = icmp ule ptr [[TMP5]], [[WIDE_PTR_UB]], !annotation [[META2]] +// X86_64-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] // X86_64: trap: // X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1:[0-9]+]], !annotation [[META2]] // X86_64-NEXT: br label [[CONT]], !annotation [[META2]] // X86_64: cont: -// X86_64-NEXT: [[TMP7:%.*]] = icmp uge ptr [[TMP5]], [[WIDE_PTR_LB]], !annotation [[META3:![0-9]+]] -// X86_64-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !annotation [[META3]] +// X86_64-NEXT: [[TMP7:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP5]], !annotation [[META2]] +// X86_64-NEXT: br i1 [[TMP7]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], !annotation [[META2]] // X86_64: trap1: -// X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META3]] -// X86_64-NEXT: br label [[CONT2]], !annotation [[META3]] +// X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META2]] +// X86_64-NEXT: br label [[CONT2]], !annotation [[META2]] // X86_64: cont2: -// X86_64-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP5]], align 4 -// X86_64-NEXT: ret i32 [[TMP8]] +// X86_64-NEXT: [[TMP8:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]] +// X86_64-NEXT: br i1 [[TMP8]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], !annotation [[META4]] +// X86_64: trap3: +// X86_64-NEXT: call void @fb_trap(i8 25) #[[ATTR1]], !annotation [[META4]] +// X86_64-NEXT: br label [[CONT4]], !annotation [[META4]] +// X86_64: cont4: +// X86_64-NEXT: [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// X86_64-NEXT: ret i32 [[TMP9]] // int foo(int *__counted_by(count) bar, unsigned count) { return bar[1]; } -//. -// X86_64: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} -// X86_64: [[META3]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} -//. diff --git a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c index fab6e75649132..a052918bec6ef 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c +++ b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-addr_of_struct_member-O0.c @@ -25,7 +25,7 @@ int* TYPE operation(Data_t* TYPE d) { } // In first copy of the file -// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-le-upper-bound"} // CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Pointer to struct above bounds while taking address of struct member", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} // CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) // CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 24, column: 12, scope: {{![0-9]+}}) @@ -34,7 +34,11 @@ int* TYPE operation(Data_t* TYPE d) { // In second copy of the file // CHECK-LABEL: @operation // Note: We use the `OPT_REMARK` to make sure we match against the correct branch. -// Unfortunately `SRC_LOC` is not enough because it isn't unique. -// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation [[OPT_REMARK]] -// CHECK: [[TRAP_LABEL]]: +// FIXME: The overflow check should have its own opt-remark (rdar://150322607) +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_0:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_0]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] + +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_1:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof ![[PROFILE_METADATA:[0-9]+]], !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_1]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c index af2be0ad09712..dbdf567bf6612 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c +++ b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-cast-O0.c @@ -1,20 +1,40 @@ -// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_bidi.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_bidi.ll %t.sep %t_bidi.ll > %t_bidi.repeated.ll +// RUN: FileCheck %s --input-file=%t_bidi.repeated.ll + +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_idx.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_idx.ll %t.sep %t_idx.ll > %t_idx.repeated.ll +// RUN: FileCheck %s --input-file=%t_idx.repeated.ll + #include +#ifndef TYPE +#error TYPE must be defined +#endif + int* __single operation(int* TYPE i) { return i; } +// In first copy of the file + +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Pointer above bounds while casting", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) +// CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 19, column: 12, scope: {{![0-9]+}}) +// CHECK-LABEL: ; __SEPARATOR__ + +// In second copy of the file // CHECK-LABEL: @operation -// We don't try to match the registers used in the comparison because trying -// to match the IR is very fragile. -// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] -// CHECK: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] -// CHECK: [[TRAP_LABEL]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] - -// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) -// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Pointer above bounds while casting", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{.+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} -// CHECK-DAG: [[LOC]] = !DILocation(line: 7, column: 12, scope: {{![0-9]+}}) +// Note: We use the `OPT_REMARK` to make sure we match against the correct branch. +// FIXME: The overflow check should have its own opt-remark (rdar://150322607) +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_0:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_0]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] + +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_1:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c index 9088cb3a42c54..fa7fa5b5b7760 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c +++ b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-array_subscript-O0.c @@ -1,19 +1,32 @@ -// RUN: %clang_cc1 -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t.ll %t.sep %t.ll > %t.repeated.ll +// RUN: FileCheck %s --input-file=%t.repeated.ll + int operation(int index) { int array[] = {0, 1, 2}; return array[index]; } +// In first copy of the file + +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) +// CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 10, column: 10, scope: {{![0-9]+}}) +// CHECK-LABEL: ; __SEPARATOR__ + +// In second copy of the file + // CHECK-LABEL: @operation -// We don't try to match the registers used in the comparison because trying -// to match the IR is very fragile. -// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] -// CHECK-NEXT: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] -// CHECK: [[TRAP_LABEL]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] - -// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) -// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} -// CHECK-DAG: [[LOC]] = !DILocation(line: 6, column: 10, scope: {{![0-9]+}}) +// Note: We use the `OPT_REMARK` to make sure we match against the correct branch. +// FIXME: The overflow check should have its own opt-remark (rdar://150322607) +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_0:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_0]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] + +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_1:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-member_access-O0.c b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-member_access-O0.c index 836758b2ee021..16f2b50267019 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-member_access-O0.c +++ b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-member_access-O0.c @@ -1,6 +1,14 @@ -// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_bidi.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_bidi.ll %t.sep %t_bidi.ll > %t_bidi.repeated.ll +// RUN: FileCheck %s --input-file=%t_bidi.repeated.ll + +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_idx.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_idx.ll %t.sep %t_idx.ll > %t_idx.repeated.ll +// RUN: FileCheck %s --input-file=%t_idx.repeated.ll + #include #ifndef TYPE @@ -16,14 +24,19 @@ int operation(Data_t* TYPE d) { return d->a; } +// In first copy of the file + +// FIXME: This is the wrong opt-remark. It should be "bounds-safety-check-ptr-le-upper-bound" rdar://150380319 +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) +// CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 24, column: 15, scope: {{![0-9]+}}) +// CHECK-LABEL: ; __SEPARATOR__ + +// In second copy of the file + // CHECK-LABEL: @operation -// We don't try to match the registers used in the comparison because trying -// to match the IR is very fragile. -// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ule ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] -// CHECK-NEXT: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] -// CHECK: [[TRAP_LABEL]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] - -// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) -// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} -// CHECK-DAG: [[LOC]] = !DILocation(line: 16, column: 15, scope: {{![0-9]+}}) +// Note: We use the `OPT_REMARK` to make sure we match against the correct branch. +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_0:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_0]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c index f296f55a5aa34..faeacf4b5fa87 100644 --- a/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c +++ b/clang/test/BoundsSafety/CodeGen/trap-reasons/ptr_ge_upper_bound-deref-unary-O0.c @@ -1,6 +1,14 @@ -// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DTYPE=__bidi_indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_bidi.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_bidi.ll %t.sep %t_bidi.ll > %t_bidi.repeated.ll +// RUN: FileCheck %s --input-file=%t_bidi.repeated.ll + +// RUN: %clang_cc1 -DTYPE=__indexable -O0 -debug-info-kind=standalone -dwarf-version=5 -fbounds-safety -emit-llvm %s -o %t_idx.ll +// RUN: echo "; __SEPARATOR__" > %t.sep +// RUN: cat %t_idx.ll %t.sep %t_idx.ll > %t_idx.repeated.ll +// RUN: FileCheck %s --input-file=%t_idx.repeated.ll + #include #ifndef TYPE @@ -11,14 +19,23 @@ int operation(int* TYPE i) { return *i; } +// In first copy of the file + +// CHECK-DAG: [[OPT_REMARK:![0-9]+]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK-DAG: [[TRAP_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE:![0-9]+]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} +// CHECK-DAG: [[TRAP_LOC:![0-9]+]] = !DILocation(line: 0, scope: [[TRAP_SCOPE]], inlinedAt: [[SRC_LOC:![0-9]+]]) +// CHECK-DAG: [[SRC_LOC]] = !DILocation(line: 19, column: 12, scope: {{![0-9]+}}) +// CHECK-LABEL: ; __SEPARATOR__ + +// In second copy of the file + // CHECK-LABEL: @operation -// We don't try to match the registers used in the comparison because trying -// to match the IR is very fragile. -// CHECK: [[BRANCH_REG:%[0-9]+]] = icmp ult ptr %{{.+}}, %{{.+}}, !dbg [[LOC:![0-9]+]] -// CHECK-NEXT: br i1 [[BRANCH_REG]], label {{.+}}, label %[[TRAP_LABEL:[a-z0-9]+]], !dbg [[LOC]] -// CHECK: [[TRAP_LABEL]]: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC:![0-9]+]] - -// CHECK-DAG: [[TRAP_LOC]] = !DILocation(line: 0, scope: [[TRAP_SCOPE:![0-9]+]], inlinedAt: [[LOC]]) -// CHECK-DAG: [[TRAP_SCOPE]] = distinct !DISubprogram(name: "__clang_trap_msg$Bounds check failed$Dereferencing above bounds", scope: [[FILE_SCOPE:![0-9]+]], file: [[FILE_SCOPE]], type: {{![0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: {{![0-9]+}} -// CHECK-DAG: [[LOC]] = !DILocation(line: 11, column: 12, scope: {{![0-9]+}}) +// Note: We use the `OPT_REMARK` to make sure we match against the correct branch. +// FIXME: The overflow check should have its own opt-remark (rdar://150322607) +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_0:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_0]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] + +// CHECK: br i1 %{{.+}}, label %{{.+}}, label %[[TRAP_LABEL_1:[a-z0-9]+]], !dbg [[SRC_LOC]], !prof !{{[0-9]+}}, !annotation [[OPT_REMARK]] +// CHECK: [[TRAP_LABEL_1]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) {{.*}}!dbg [[TRAP_LOC]] diff --git a/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c b/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c index 6f452255250c8..e4233f34c7b2c 100644 --- a/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c +++ b/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O0-O2-opt-disabled.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5 - // RUN: %clang_cc1 -O0 -triple arm64e-apple-ios -fbounds-safety \ // RUN: -funique-traps -emit-llvm %s -o - \ // RUN: | FileCheck -check-prefix=OPT0 %s @@ -30,22 +29,30 @@ int consume(int* __bidi_indexable ptr, int idx) { // OPT0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // OPT0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // OPT0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// OPT0-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META2:![0-9]+]] -// OPT0-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] +// OPT0-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, !annotation [[META2:![0-9]+]] +// OPT0-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], !annotation [[META2]] +// OPT0-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] // OPT0: [[TRAP]]: // OPT0-NEXT: call void asm sideeffect "", "n"(i64 0), !annotation [[META2]] // OPT0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META2]] // OPT0-NEXT: unreachable, !annotation [[META2]] // OPT0: [[CONT]]: -// OPT0-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]] -// OPT0-NEXT: br i1 [[TMP2]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]] +// OPT0-NEXT: [[TMP3:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP1]], !annotation [[META2]] +// OPT0-NEXT: br i1 [[TMP3]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META2]] // OPT0: [[TRAP1]]: -// OPT0-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META4]] +// OPT0-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META2]] +// OPT0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META2]] +// OPT0-NEXT: unreachable, !annotation [[META2]] +// OPT0: [[CONT2]]: +// OPT0-NEXT: [[TMP4:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]] +// OPT0-NEXT: br i1 [[TMP4]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]] +// OPT0: [[TRAP3]]: +// OPT0-NEXT: call void asm sideeffect "", "n"(i64 2), !annotation [[META4]] // OPT0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META4]] // OPT0-NEXT: unreachable, !annotation [[META4]] -// OPT0: [[CONT2]]: -// OPT0-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -// OPT0-NEXT: ret i32 [[TMP3]] +// OPT0: [[CONT4]]: +// OPT0-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// OPT0-NEXT: ret i32 [[TMP5]] // // // OPT2-LABEL: define i32 @consume( @@ -66,25 +73,33 @@ int consume(int* __bidi_indexable ptr, int idx) { // OPT2-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // OPT2-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // OPT2-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// OPT2-NEXT: [[TMP1:%.*]] = icmp ult ptr [[ARRAYIDX]], [[WIDE_PTR_UB]], !annotation [[META13:![0-9]+]] -// OPT2-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF14:![0-9]+]], !annotation [[META13]] +// OPT2-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, !annotation [[META13:![0-9]+]] +// OPT2-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], !annotation [[META13]] +// OPT2-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF14:![0-9]+]], !annotation [[META13]] // OPT2: [[TRAP]]: // OPT2-NEXT: call void asm sideeffect "", "n"(i64 0), !annotation [[META13]] // OPT2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META13]] // OPT2-NEXT: unreachable, !annotation [[META13]] // OPT2: [[CONT]]: -// OPT2-NEXT: [[TMP2:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META15:![0-9]+]] -// OPT2-NEXT: br i1 [[TMP2]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF14]], !annotation [[META15]] +// OPT2-NEXT: [[TMP3:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP1]], !annotation [[META13]] +// OPT2-NEXT: br i1 [[TMP3]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF14]], !annotation [[META13]] // OPT2: [[TRAP1]]: -// OPT2-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META15]] +// OPT2-NEXT: call void asm sideeffect "", "n"(i64 1), !annotation [[META13]] +// OPT2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META13]] +// OPT2-NEXT: unreachable, !annotation [[META13]] +// OPT2: [[CONT2]]: +// OPT2-NEXT: [[TMP4:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META15:![0-9]+]] +// OPT2-NEXT: br i1 [[TMP4]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF14]], !annotation [[META15]] +// OPT2: [[TRAP3]]: +// OPT2-NEXT: call void asm sideeffect "", "n"(i64 2), !annotation [[META15]] // OPT2-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], !annotation [[META15]] // OPT2-NEXT: unreachable, !annotation [[META15]] -// OPT2: [[CONT2]]: -// OPT2-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA8]] -// OPT2-NEXT: ret i32 [[TMP3]] +// OPT2: [[CONT4]]: +// OPT2-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA8]] +// OPT2-NEXT: ret i32 [[TMP5]] // //. -// OPT0: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// OPT0: [[META2]] = !{!"bounds-safety-check-ptr-le-upper-bound"} // OPT0: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} // OPT0: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} //. @@ -99,7 +114,7 @@ int consume(int* __bidi_indexable ptr, int idx) { // OPT2: [[TBAA_STRUCT10]] = !{i64 0, i64 24, [[META11:![0-9]+]]} // OPT2: [[META11]] = !{[[META12:![0-9]+]], [[META12]], i64 0} // OPT2: [[META12]] = !{!"p1 int", [[META5]], i64 0} -// OPT2: [[META13]] = !{!"bounds-safety-check-ptr-lt-upper-bound"} +// OPT2: [[META13]] = !{!"bounds-safety-check-ptr-le-upper-bound"} // OPT2: [[PROF14]] = !{!"branch_weights", i32 1048575, i32 1} // OPT2: [[META15]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} //. diff --git a/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O2.c b/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O2.c index 134094fed2836..75041f46244bd 100644 --- a/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O2.c +++ b/clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O2.c @@ -1,6 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5 - // Make sure that with or without `-fsplit-cold-code` that the trap blocks don't // get outlined into their own function. Outlining trap blocks is unhelpful // because it makes debugging harder which is the opposite of what @@ -12,6 +11,11 @@ // RUN: %clang_cc1 -O2 -triple arm64e-apple-ios -fbounds-safety \ // RUN: -funique-traps -emit-llvm %s -o - -fsplit-cold-code \ // RUN: | FileCheck %s + +// FIXME: When using `-fsplit-cold-code` it looks like traps are getting split +// (rdar://150559639). +// XFAIL: * + #include __attribute__((always_inline)) int i_want_to_be_inlined( @@ -25,5 +29,114 @@ int consume(int* __bidi_indexable ptr, int* __bidi_indexable ptr2, int idx) { int other = i_want_to_be_inlined(ptr2, idx); return ptr[idx]; } -//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -// CHECK: {{.*}} +// CHECK-LABEL: define i32 @i_want_to_be_inlined( +// CHECK-SAME: ptr noundef readonly captures(none) [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_2_0_PTR_SROA_IDX]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 16 +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_PTR_SROA_IDX]], align 8, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], i64 [[IDXPROM]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, !annotation [[META7:![0-9]+]] +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[AGG_TEMP_SROA_2_0_COPYLOAD]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF8:![0-9]+]], !annotation [[META7]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 0) #[[ATTR3:[0-9]+]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[DOTNOT5:%.*]] = icmp ugt ptr [[ARRAYIDX]], [[TMP0]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT5]], label %[[TRAP1:.*]], label %[[CONT2:.*]], !prof [[PROF8]], !annotation [[META7]] +// CHECK: [[TRAP1]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 1) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[DOTNOT6:%.*]] = icmp ult ptr [[ARRAYIDX]], [[AGG_TEMP_SROA_3_0_COPYLOAD]], !annotation [[META9:![0-9]+]] +// CHECK-NEXT: br i1 [[DOTNOT6]], label %[[TRAP3:.*]], label %[[CONT4:.*]], !prof [[PROF8]], !annotation [[META9]] +// CHECK: [[TRAP3]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 2) #[[ATTR3]], !annotation [[META9]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: [[CONT4]]: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA10:![0-9]+]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +// +// CHECK-LABEL: define i32 @consume( +// CHECK-SAME: ptr noundef readonly captures(none) [[PTR:%.*]], ptr noundef readonly captures(none) [[PTR2:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[BYVAL_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[PTR2]], align 8 +// CHECK-NEXT: [[BYVAL_TEMP_SROA_4_0_PTR2_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR2]], i64 8 +// CHECK-NEXT: [[BYVAL_TEMP_SROA_4_0_COPYLOAD:%.*]] = load ptr, ptr [[BYVAL_TEMP_SROA_4_0_PTR2_SROA_IDX]], align 8 +// CHECK-NEXT: [[BYVAL_TEMP_SROA_5_0_PTR2_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR2]], i64 16 +// CHECK-NEXT: [[BYVAL_TEMP_SROA_5_0_COPYLOAD:%.*]] = load ptr, ptr [[BYVAL_TEMP_SROA_5_0_PTR2_SROA_IDX]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[IDXPROM_I:%.*]] = sext i32 [[IDX]] to i64 +// CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr i32, ptr [[BYVAL_TEMP_SROA_0_0_COPYLOAD]], i64 [[IDXPROM_I]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[ARRAYIDX_I]], i64 4, !annotation [[META7]] +// CHECK-NEXT: [[DOTNOT_I:%.*]] = icmp ugt ptr [[TMP0]], [[BYVAL_TEMP_SROA_4_0_COPYLOAD]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT_I]], label %[[TRAP_I:.*]], label %[[CONT_I:.*]], !prof [[PROF8]], !annotation [[META7]] +// CHECK: [[TRAP_I]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 0) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT_I]]: +// CHECK-NEXT: [[DOTNOT5_I:%.*]] = icmp ugt ptr [[ARRAYIDX_I]], [[TMP0]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT5_I]], label %[[TRAP1_I:.*]], label %[[CONT2_I:.*]], !prof [[PROF8]], !annotation [[META7]] +// CHECK: [[TRAP1_I]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 1) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT2_I]]: +// CHECK-NEXT: [[DOTNOT6_I:%.*]] = icmp ult ptr [[ARRAYIDX_I]], [[BYVAL_TEMP_SROA_5_0_COPYLOAD]], !annotation [[META9]] +// CHECK-NEXT: br i1 [[DOTNOT6_I]], label %[[TRAP3_I:.*]], label %[[I_WANT_TO_BE_INLINED_EXIT:.*]], !prof [[PROF8]], !annotation [[META9]] +// CHECK: [[TRAP3_I]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 2) #[[ATTR3]], !annotation [[META9]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: [[I_WANT_TO_BE_INLINED_EXIT]]: +// CHECK-NEXT: [[AGG_TEMP_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_2_0_PTR_SROA_IDX]], align 8 +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_PTR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 16 +// CHECK-NEXT: [[AGG_TEMP_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP_SROA_3_0_PTR_SROA_IDX]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[AGG_TEMP_SROA_0_0_COPYLOAD]], i64 [[IDXPROM_I]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[ARRAYIDX]], i64 4, !annotation [[META7]] +// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP1]], [[AGG_TEMP_SROA_2_0_COPYLOAD]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF8]], !annotation [[META7]] +// CHECK: [[TRAP]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 3) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT]]: +// CHECK-NEXT: [[DOTNOT6:%.*]] = icmp ugt ptr [[ARRAYIDX]], [[TMP1]], !annotation [[META7]] +// CHECK-NEXT: br i1 [[DOTNOT6]], label %[[TRAP1:.*]], label %[[CONT2:.*]], !prof [[PROF8]], !annotation [[META7]] +// CHECK: [[TRAP1]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 4) #[[ATTR3]], !annotation [[META7]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META7]] +// CHECK-NEXT: unreachable, !annotation [[META7]] +// CHECK: [[CONT2]]: +// CHECK-NEXT: [[DOTNOT7:%.*]] = icmp ult ptr [[ARRAYIDX]], [[AGG_TEMP_SROA_3_0_COPYLOAD]], !annotation [[META9]] +// CHECK-NEXT: br i1 [[DOTNOT7]], label %[[TRAP3:.*]], label %[[CONT4:.*]], !prof [[PROF8]], !annotation [[META9]] +// CHECK: [[TRAP3]]: +// CHECK-NEXT: tail call void asm sideeffect "", "n"(i64 5) #[[ATTR3]], !annotation [[META9]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], !annotation [[META9]] +// CHECK-NEXT: unreachable, !annotation [[META9]] +// CHECK: [[CONT4]]: +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA10]] +// CHECK-NEXT: ret i32 [[TMP2]] +// +//. +// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0} +// CHECK: [[META3]] = !{!"p1 int", [[META4:![0-9]+]], i64 0} +// CHECK: [[META4]] = !{!"any pointer", [[META5:![0-9]+]], i64 0} +// CHECK: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[META7]] = !{!"bounds-safety-check-ptr-le-upper-bound"} +// CHECK: [[PROF8]] = !{!"branch_weights", i32 1, i32 1048575} +// CHECK: [[META9]] = !{!"bounds-safety-check-ptr-ge-lower-bound"} +// CHECK: [[TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0} +// CHECK: [[META11]] = !{!"int", [[META5]], i64 0} +//. diff --git a/clang/test/BoundsSafety/CodeGen/wide-ptr-assign-O2.c b/clang/test/BoundsSafety/CodeGen/wide-ptr-assign-O2.c index fe937a5e5dc76..27b218bc370c8 100644 --- a/clang/test/BoundsSafety/CodeGen/wide-ptr-assign-O2.c +++ b/clang/test/BoundsSafety/CodeGen/wide-ptr-assign-O2.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O2 -fbounds-safety -emit-llvm -triple arm64 %s -o - | FileCheck %s // RUN: %clang_cc1 -O2 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64 %s -o - | FileCheck %s @@ -28,20 +27,8 @@ void wide_array_subscript_trap1() { // CHECK-LABEL: @wide_array_subscript_trap2( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ARR:%.*]] = alloca [5 x %"__bounds_safety::wide_ptr.indexable"], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 80, ptr nonnull [[ARR]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds nuw i8, ptr [[ARR]], i64 80 -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[ARR]], i64 -16 -// CHECK-NEXT: [[TMP0:%.*]] = icmp ult ptr [[ARRAYIDX]], [[UPPER]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP1:%.*]] = icmp uge ptr [[ARRAYIDX]], [[ARR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TMP0]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: -// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont1: -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 80, ptr nonnull [[ARR]]) #[[ATTR6]] -// CHECK-NEXT: ret void // void wide_array_subscript_trap2() { int *__indexable arr[5]; @@ -117,11 +104,11 @@ void wide_member_assign_ok() { // CHECK-LABEL: @wide_member_assign_trap( // CHECK-NEXT: entry: // CHECK-NEXT: [[W:%.*]] = alloca [[STRUCT_WIDE_MEMBER_T:%.*]], align 8 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[W]]) #[[ATTR6]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[W]]) #[[ATTR6:[0-9]+]] // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[W]], i64 24 // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[W]], i64 48 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP1]], [[TMP0]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT1:%.*]], !prof [[PROF5:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} diff --git a/clang/test/BoundsSafety/CodeGen/wide-ptr-assign.c b/clang/test/BoundsSafety/CodeGen/wide-ptr-assign.c index 11d39a23dbf65..496d3cd460fd8 100644 --- a/clang/test/BoundsSafety/CodeGen/wide-ptr-assign.c +++ b/clang/test/BoundsSafety/CodeGen/wide-ptr-assign.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -O0 -fbounds-safety -emit-llvm -triple arm64 %s -o - | FileCheck %s // RUN: %clang_cc1 -O0 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm -triple arm64 %s -o - | FileCheck %s @@ -28,24 +27,31 @@ // CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP3]] to i64 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[TMP4]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap6: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont7: -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 16, i1 false) +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[ARRAYIDX]], i8 0, i64 16, i1 false) // CHECK-NEXT: ret void // void wide_array_subscript(int *__indexable *__indexable buf, int i) { @@ -75,23 +81,30 @@ void wide_array_subscript(int *__indexable *__indexable buf, int i) { // CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP3]] to i64 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 [[IDXPROM]] // CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = icmp ult ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP5:%.*]] = icmp ule ptr [[TMP4]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP6:%.*]] = icmp uge ptr [[TMP4]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label [[CONT7:%.*]], label [[TRAP6:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap6: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont7: +// CHECK-NEXT: [[TMP7:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP7]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: // CHECK-NEXT: ret void // void wide_array_subscript_load(int *__indexable *__indexable buf, int i) { @@ -180,18 +193,25 @@ void wide_array_subscript_addr(int *__indexable *__indexable buf, int i) { // CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 // CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = icmp ult ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr %"__bounds_safety::wide_ptr.indexable.0", ptr [[WIDE_PTR_PTR3]], i64 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP14:%.*]] = icmp ule ptr [[TMP13]], [[WIDE_PTR_UB5]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: -// CHECK-NEXT: [[TMP14:%.*]] = icmp uge ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP14]], label [[CONT7:%.*]], label [[TRAP6:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP15:%.*]] = icmp ule ptr [[WIDE_PTR_PTR3]], [[TMP13]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label [[CONT7:%.*]], label [[TRAP6:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap6: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont7: +// CHECK-NEXT: [[TMP16:%.*]] = icmp uge ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP16]], label [[CONT9:%.*]], label [[TRAP8:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: trap8: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: cont9: // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[WIDE_PTR_PTR3]], i8 0, i64 16, i1 false) // CHECK-NEXT: ret void // @@ -216,13 +236,13 @@ struct wide_member_t { // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_WIDE_MEMBER_T:%.*]], ptr [[WIDE_PTR_PTR]], i64 1 // CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK: cont: // CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[WIDE_PTR_LB]], [[WIDE_PTR_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP2]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK: trap1: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} diff --git a/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-addrof-deref.c b/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-addrof-deref.c index 32aa2efd8fec9..8ad18d60ffd65 100644 --- a/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-addrof-deref.c +++ b/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-addrof-deref.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 @@ -23,30 +22,37 @@ // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR2]], i64 24, i1 false) // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 10 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP6]] +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP7]] // // CHECK-O2-LABEL: @foo( // CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int foo() { int arr[10]; @@ -73,25 +79,32 @@ int foo() { // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[PTR2]], i64 24, i1 false) // CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-O0-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR]], i64 9 // CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP4:%.*]] = icmp ule ptr [[TMP3]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP4]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp uge ptr [[TMP3]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP5:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP5]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP6]] +// CHECK-O0-NEXT: [[TMP6:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP6]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP7]] // // CHECK-O2-LABEL: @bar( // CHECK-O2-NEXT: entry: diff --git a/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-deref-addrof.c b/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-deref-addrof.c index e1cf0a79792ad..f4a536b5c3e20 100644 --- a/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-deref-addrof.c +++ b/clang/test/BoundsSafety/CodeGen/wide-ptr-bound-deref-addrof.c @@ -1,5 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" - // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -O2 -triple arm64-apple-iphoneos -fbounds-safety -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O2 // RUN: %clang_cc1 -O0 -triple arm64-apple-iphoneos -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 @@ -14,7 +13,7 @@ // CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-O0-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 // CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 @@ -36,46 +35,60 @@ // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR2]], i64 24, i1 false) -// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 10 -// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-O0-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: trap10: +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable -// CHECK-O0: cont11: -// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 10 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap12: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont13: -// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP12]] +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap14: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont15: +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap16: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont17: +// CHECK-O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP15]] // // CHECK-O2-LABEL: @foo( -// CHECK-O2-NEXT: trap: +// CHECK-O2-NEXT: entry: // CHECK-O2-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} -// CHECK-O2-NEXT: unreachable +// CHECK-O2-NEXT: unreachable, {{!annotation ![0-9]+}} // int foo() { int arr[10]; @@ -90,7 +103,7 @@ int foo() { // CHECK-O0-NEXT: [[PTR:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[PTR2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-O0-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-O0-NEXT: [[AGG_TEMP5:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-O0-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARR]], i64 0, i64 0 // CHECK-O0-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 10 // CHECK-O0-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[PTR]], i32 0, i32 0 @@ -112,41 +125,55 @@ int foo() { // CHECK-O0-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 // CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-O0-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-O0-NEXT: [[TMP7:%.*]] = icmp ult ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP7]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP7:%.*]] = getelementptr %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[WIDE_PTR_PTR]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT:%.*]], label [[TRAP:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont: -// CHECK-O0-NEXT: [[TMP8:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP8]], label [[CONT2:%.*]], label [[TRAP1:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP9:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[TMP7]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP9]], label [[CONT2:%.*]], label [[TRAP1:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap1: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont2: -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) -// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP3]], ptr align 8 [[PTR2]], i64 24, i1 false) -// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-O0-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-O0-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR5]], i64 9 -// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-O0-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-O0-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[WIDE_PTR_UB7]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT11:%.*]], label [[TRAP10:%.*]], {{!annotation ![0-9]+}} -// CHECK-O0: trap10: +// CHECK-O0-NEXT: [[TMP10:%.*]] = icmp uge ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_LB]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP10]], label [[CONT4:%.*]], label [[TRAP3:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap3: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable -// CHECK-O0: cont11: -// CHECK-O0-NEXT: [[TMP11:%.*]] = icmp uge ptr [[TMP9]], [[WIDE_PTR_LB9]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: br i1 [[TMP11]], label [[CONT13:%.*]], label [[TRAP12:%.*]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont4: +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[PTR2]], ptr align 8 [[WIDE_PTR_PTR]], i64 24, i1 false) +// CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP5]], ptr align 8 [[PTR2]], i64 24, i1 false) +// CHECK-O0-NEXT: [[WIDE_PTR_PTR_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 0 +// CHECK-O0-NEXT: [[WIDE_PTR_PTR7:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR6]], align 8 +// CHECK-O0-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[WIDE_PTR_PTR7]], i64 9 +// CHECK-O0-NEXT: [[WIDE_PTR_UB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 1 +// CHECK-O0-NEXT: [[WIDE_PTR_UB9:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR8]], align 8 +// CHECK-O0-NEXT: [[WIDE_PTR_LB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP5]], i32 0, i32 2 +// CHECK-O0-NEXT: [[WIDE_PTR_LB11:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR10]], align 8 +// CHECK-O0-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[ARRAYIDX]], i64 1, {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: [[TMP12:%.*]] = icmp ule ptr [[TMP11]], [[WIDE_PTR_UB9]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP12]], label [[CONT13:%.*]], label [[TRAP12:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} // CHECK-O0: trap12: // CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} -// CHECK-O0-NEXT: unreachable +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} // CHECK-O0: cont13: -// CHECK-O0-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK-O0-NEXT: ret i32 [[TMP12]] +// CHECK-O0-NEXT: [[TMP13:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP13]], label [[CONT15:%.*]], label [[TRAP14:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap14: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont15: +// CHECK-O0-NEXT: [[TMP14:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB11]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: br i1 [[TMP14]], label [[CONT17:%.*]], label [[TRAP16:%.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK-O0: trap16: +// CHECK-O0-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR3]], {{!annotation ![0-9]+}} +// CHECK-O0-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK-O0: cont17: +// CHECK-O0-NEXT: [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-O0-NEXT: ret i32 [[TMP15]] // // CHECK-O2-LABEL: @bar( // CHECK-O2-NEXT: entry: diff --git a/clang/test/BoundsSafety/CodeGen/zero-length-pointers.c b/clang/test/BoundsSafety/CodeGen/zero-length-pointers.c index b35b1d12cf7a9..17542680355f9 100644 --- a/clang/test/BoundsSafety/CodeGen/zero-length-pointers.c +++ b/clang/test/BoundsSafety/CodeGen/zero-length-pointers.c @@ -1,6 +1,5 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 5 // REQUIRES: system-darwin -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ - // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -emit-llvm %s -o - -O2 | FileCheck %s --check-prefix CHECK-O2 // RUN: %clang_cc1 -triple x86_64 -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -emit-llvm %s -o - | FileCheck %s @@ -11,8 +10,9 @@ typedef __SIZE_TYPE__ size_t; void counted_by(int *__counted_by(len) p, size_t len); -// CHECK-LABEL: @test_counted_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_counted_by( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 @@ -55,8 +55,8 @@ void counted_by(int *__counted_by(len) p, size_t len); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_PTR6]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} -// CHECK: land.lhs.true: +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_LHS_TRUE]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} @@ -76,8 +76,8 @@ void counted_by(int *__counted_by(len) p, size_t len); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP20]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP27:%.*]] = icmp ule ptr [[WIDE_PTR_PTR15]], [[WIDE_PTR_PTR22]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP27]], label [[LAND_RHS:%.*]], label [[LAND_END]], {{!annotation ![0-9]+}} -// CHECK: land.rhs: +// CHECK-NEXT: br i1 [[CMP27]], label %[[LAND_RHS:.*]], label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, {{!annotation ![0-9]+}} @@ -101,14 +101,14 @@ void counted_by(int *__counted_by(len) p, size_t len); // CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP44:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} -// CHECK: land.end: -// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[CMP44]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP6]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[CMP44]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont: +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP45]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP45]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 @@ -160,11 +160,11 @@ void counted_by(int *__counted_by(len) p, size_t len); // CHECK-NEXT: [[SUB_PTR_SUB71:%.*]] = sub i64 [[SUB_PTR_LHS_CAST69]], [[SUB_PTR_RHS_CAST70]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_DIV72:%.*]] = sdiv exact i64 [[SUB_PTR_SUB71]], 4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP73:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV72]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP73]], label [[CONT75:%.*]], label [[TRAP74:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap74: +// CHECK-NEXT: br i1 [[CMP73]], label %[[CONT75:.*]], label %[[TRAP74:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP74]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont75: +// CHECK: [[CONT75]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP76]], ptr align 8 [[AGG_TEMP52]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR77:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP76]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR78:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR77]], align 8 @@ -175,8 +175,9 @@ void counted_by(int *__counted_by(len) p, size_t len); // CHECK-NEXT: call void @counted_by(ptr noundef [[WIDE_PTR_PTR78]], i64 noundef 0) // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_counted_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_counted_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4:[0-9]+]] @@ -196,8 +197,9 @@ void test_counted_by(void) { } void sized_by(void *__sized_by(len) p, size_t len); -// CHECK-LABEL: @test_sized_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_sized_by( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 @@ -258,8 +260,8 @@ void sized_by(void *__sized_by(len) p, size_t len); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR4]], [[WIDE_PTR_PTR13]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} -// CHECK: land.lhs.true: +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_LHS_TRUE]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} @@ -279,8 +281,8 @@ void sized_by(void *__sized_by(len) p, size_t len); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP34:%.*]] = icmp ule ptr [[WIDE_PTR_PTR22]], [[WIDE_PTR_PTR29]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP34]], label [[LAND_RHS:%.*]], label [[LAND_END]], {{!annotation ![0-9]+}} -// CHECK: land.rhs: +// CHECK-NEXT: br i1 [[CMP34]], label %[[LAND_RHS:.*]], label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP36]], i32 0, i32 1, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, {{!annotation ![0-9]+}} @@ -327,14 +329,14 @@ void sized_by(void *__sized_by(len) p, size_t len); // CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR60]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP65:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} -// CHECK: land.end: -// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[LAND_LHS_TRUE]] ], [ false, [[ENTRY:%.*]] ], [ [[CMP65]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP15]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP15:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[CMP65]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP15]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont: +// CHECK: [[CONT]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP66]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP66]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR68:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR67]], align 8 @@ -421,11 +423,11 @@ void sized_by(void *__sized_by(len) p, size_t len); // CHECK-NEXT: [[SUB_PTR_RHS_CAST112:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR106]] to i64, {{!annotation ![0-9]+}} // CHECK-NEXT: [[SUB_PTR_SUB113:%.*]] = sub i64 [[SUB_PTR_LHS_CAST111]], [[SUB_PTR_RHS_CAST112]], {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP114:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB113]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP114]], label [[CONT116:%.*]], label [[TRAP115:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap115: +// CHECK-NEXT: br i1 [[CMP114]], label %[[CONT116:.*]], label %[[TRAP115:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP115]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont116: +// CHECK: [[CONT116]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP117]], ptr align 8 [[AGG_TEMP73]], i64 24, i1 false) // CHECK-NEXT: [[WIDE_PTR_PTR_ADDR118:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP117]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR119:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR118]], align 8 @@ -436,8 +438,9 @@ void sized_by(void *__sized_by(len) p, size_t len); // CHECK-NEXT: call void @sized_by(ptr noundef [[WIDE_PTR_PTR119]], i64 noundef 0) // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_sized_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_sized_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] @@ -457,8 +460,9 @@ void test_sized_by(void) { } void ended_by(void *__ended_by(end) start, void *end); -// CHECK-LABEL: @test_ended_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_ended_by( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 @@ -468,19 +472,19 @@ void ended_by(void *__ended_by(end) start, void *end); // CHECK-NEXT: [[AGG_TEMP12:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP19:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP28:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP37:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP45:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP59:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP60:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP65:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[TMP_TMP67:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP75:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP82:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP92:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP99:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP67:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP68:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP69:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP77:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP86:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP96:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP103:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 @@ -540,149 +544,158 @@ void ended_by(void *__ended_by(end) start, void *end); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP19]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB27:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR26]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR14]], [[WIDE_PTR_PTR23]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]], {{!annotation ![0-9]+}} -// CHECK: land.rhs: +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP28]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR30:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR29]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB32:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR31]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB34:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR33]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR37:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR36]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB39:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR38]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP42:%.*]] = icmp ule ptr [[WIDE_PTR_PTR30]], [[WIDE_PTR_PTR37]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br label [[LAND_END]], {{!annotation ![0-9]+}} -// CHECK: land.end: -// CHECK-NEXT: [[TMP13:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP42]], [[LAND_RHS]] ], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[TMP13]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB30]], ptr [[TMP13]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR32:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB34:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP28]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB36:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR35]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP37]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP37]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR39:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR38]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP37]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB41:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP37]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB43:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR42]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP44:%.*]] = icmp ule ptr [[WIDE_PTR_PTR32]], [[WIDE_PTR_PTR39]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP14:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP44]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP14]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP43]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR45:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR44]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB47:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR46]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP43]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB49:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR48]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 -// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR45]], ptr noundef [[WIDE_PTR_PTR52]]) -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP15]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP16]], align 8 -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP17]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP19]], i64 1 -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP22]], ptr [[TMP23]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[TMP24]], align 8 -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP25]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR60:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR59]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB62:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR61]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP58]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB64:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR63]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR60]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB62]], ptr [[TMP28]], align 8 -// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB64]], ptr [[TMP29]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP31]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP32]], align 8 -// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP33]], align 8 -// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 0 -// CHECK-NEXT: [[TMP35:%.*]] = load ptr, ptr [[TMP34]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH68:%.*]] = getelementptr i32, ptr [[TMP35]], i64 1 -// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH68]], ptr [[TMP36]], align 8 -// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 1 -// CHECK-NEXT: [[TMP38:%.*]] = load ptr, ptr [[TMP37]], align 8 -// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP38]], ptr [[TMP39]], align 8 -// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP67]], i32 0, i32 2 -// CHECK-NEXT: [[TMP41:%.*]] = load ptr, ptr [[TMP40]], align 8 -// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP41]], ptr [[TMP42]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR69:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR70:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR69]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB72:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR71]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP66]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB74:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR73]], align 8 -// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR70]], ptr [[TMP43]], align 8 -// CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB72]], ptr [[TMP44]], align 8 -// CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP65]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB74]], ptr [[TMP45]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP75]], ptr align 8 [[AGG_TEMP57]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR76:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR77:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR76]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB79:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR78]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP75]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB81:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR80]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP82]], ptr align 8 [[AGG_TEMP65]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR84:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR83]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB86:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR85]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP82]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB88:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR87]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP89:%.*]] = icmp ule ptr [[WIDE_PTR_PTR77]], [[WIDE_PTR_PTR84]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP89]], label [[CONT91:%.*]], label [[TRAP90:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap90: +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP45]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR47:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR46]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB49:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR48]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP45]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB51:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR50]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP2]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8 +// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR47]], ptr noundef [[WIDE_PTR_PTR54]]) +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP20]], i64 1 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP26:%.*]] = load ptr, ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP26]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR61:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR62:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR61]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR63:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB64:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR63]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR65:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP60]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB66:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR65]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR62]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB64]], ptr [[TMP29]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB66]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP31]], ptr [[TMP33]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 0 +// CHECK-NEXT: [[TMP36:%.*]] = load ptr, ptr [[TMP35]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH70:%.*]] = getelementptr i32, ptr [[TMP36]], i64 1 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH70]], ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 1 +// CHECK-NEXT: [[TMP39:%.*]] = load ptr, ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP39]], ptr [[TMP40]], align 8 +// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP69]], i32 0, i32 2 +// CHECK-NEXT: [[TMP42:%.*]] = load ptr, ptr [[TMP41]], align 8 +// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP42]], ptr [[TMP43]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR71:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR72:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR71]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR73:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB74:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR73]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR75:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP68]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB76:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR75]], align 8 +// CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP67]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR72]], ptr [[TMP44]], align 8 +// CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP67]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB74]], ptr [[TMP45]], align 8 +// CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP67]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB76]], ptr [[TMP46]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP77]], ptr align 8 [[AGG_TEMP59]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR78:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP77]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB79:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR78]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP77]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB79]], ptr [[TMP47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR80:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP77]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR81:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR80]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP77]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB83:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR82]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP77]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB85:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR84]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP86]], ptr align 8 [[AGG_TEMP59]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR87:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP86]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR88:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR87]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP86]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB90:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR89]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR91:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP86]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB92:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR91]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP93:%.*]] = icmp ule ptr [[WIDE_PTR_PTR81]], [[WIDE_PTR_PTR88]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP93]], label %[[CONT95:.*]], label %[[TRAP94:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP94]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont91: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP92]], ptr align 8 [[AGG_TEMP57]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR93:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR94:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR93]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR95:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB96:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR95]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR97:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP92]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB98:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR97]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP99]], ptr align 8 [[AGG_TEMP65]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR100:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR101:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR100]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR102:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB103:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR102]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR104:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP99]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB105:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR104]], align 8 -// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR94]], ptr noundef [[WIDE_PTR_PTR101]]) +// CHECK: [[CONT95]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP96]], ptr align 8 [[AGG_TEMP59]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR97:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP96]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR98:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR97]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR99:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP96]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB100:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR99]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR101:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP96]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB102:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR101]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP103]], ptr align 8 [[AGG_TEMP67]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR104:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP103]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR105:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR104]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR106:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP103]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB107:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR106]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR108:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP103]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB109:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR108]], align 8 +// CHECK-NEXT: call void @ended_by(ptr noundef [[WIDE_PTR_PTR98]], ptr noundef [[WIDE_PTR_PTR105]]) // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_ended_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_ended_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] @@ -702,8 +715,9 @@ void test_ended_by(void) { } void ended_by_itself(void *__ended_by(end) end); -// CHECK-LABEL: @test_ended_by_itself( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_ended_by_itself( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 @@ -711,12 +725,14 @@ void ended_by_itself(void *__ended_by(end) end); // CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[AGG_TEMP18:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP25:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP33:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP52:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP59:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP69:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 @@ -756,94 +772,119 @@ void ended_by_itself(void *__ended_by(end) end); // CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP9]], i32 0, i32 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8, {{!annotation ![0-9]+}} // CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR4]], [[WIDE_PTR_PTR13]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP]], label [[CONT:%.*]], label [[TRAP:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap: +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB20]], ptr [[TMP7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR22:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB26:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP27]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP27]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP34:%.*]] = icmp ule ptr [[WIDE_PTR_PTR22]], [[WIDE_PTR_PTR29]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP8:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP34]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP8]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8 -// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR20]]) -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK: [[CONT]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP35]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR37:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR36]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB39:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR38]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP35]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8 +// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR37]]) +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[ONE]], ptr [[TMP10]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP12]], i64 1 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP13]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 -// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP19]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8 -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR28]], ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB30]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP25]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB32]], ptr [[TMP22]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP33]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP33]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false), {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB42:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR41]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: store ptr [[WIDE_PTR_UB42]], ptr [[TMP23]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_PTR44:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR43]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_UB46:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR45]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[WIDE_PTR_LB48:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR47]], align 8, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[CMP49:%.*]] = icmp ule ptr [[WIDE_PTR_PTR35]], [[WIDE_PTR_PTR44]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[CMP49]], label [[CONT51:%.*]], label [[TRAP50:%.*]], {{!annotation ![0-9]+}} -// CHECK: trap50: +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP9]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP14]], i64 1 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP20]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR45:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR44]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR46:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB47:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR46]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR48:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP43]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB49:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR48]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR45]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB47]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB49]], ptr [[TMP24]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP50]], ptr align 8 [[AGG_TEMP42]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB52:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR51]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB52]], ptr [[TMP25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP50]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP59]], ptr align 8 [[AGG_TEMP42]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR61:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR60]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB63:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR62]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR64:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP59]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB65:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR64]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP66:%.*]] = icmp ule ptr [[WIDE_PTR_PTR54]], [[WIDE_PTR_PTR61]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP66]], label %[[CONT68:.*]], label %[[TRAP67:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP67]]: // CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} // CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} -// CHECK: cont51: -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP25]], i64 24, i1 false) -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR54:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR53]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP52]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8 -// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR54]]) +// CHECK: [[CONT68]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP69]], ptr align 8 [[AGG_TEMP42]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR71:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR70]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB73:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR72]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB75:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR74]], align 8 +// CHECK-NEXT: call void @ended_by_itself(ptr noundef [[WIDE_PTR_PTR71]]) // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_ended_by_itself( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_ended_by_itself( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-O2-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] // CHECK-O2-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] // CHECK-O2-NEXT: call void @ended_by_itself(ptr noundef nonnull [[ZERO]]) #[[ATTR4]] -// CHECK-O2-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 -// CHECK-O2-NEXT: call void @ended_by_itself(ptr noundef nonnull [[TMP0]]) #[[ATTR4]] +// CHECK-O2-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr inbounds nuw i8, ptr [[ONE]], i64 4 +// CHECK-O2-NEXT: call void @ended_by_itself(ptr noundef nonnull [[BOUND_PTR_ARITH]]) #[[ATTR4]] // CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[ONE]]) #[[ATTR4]] // CHECK-O2-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr nonnull [[ZERO]]) #[[ATTR4]] // CHECK-O2-NEXT: ret void @@ -860,67 +901,150 @@ struct counted_by { size_t len; }; -// CHECK-LABEL: @test_struct_counted_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_struct_counted_by( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_COUNTED_BY:%.*]], align 8 -// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[STRUCT_COUNTED_BY]], align 8 -// CHECK-NEXT: [[AGG_TEMP3:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP4:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP7:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP15:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP18:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED33:%.*]] = alloca [[STRUCT_COUNTED_BY]], align 8 +// CHECK-NEXT: [[TMP_TMP34:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP35:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP36:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP39:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP54:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[P]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB3:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR2]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR]], [[WIDE_PTR_UB3]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP4]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP4]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB6:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR5]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP7]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR9:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB11:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR10]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP7]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP14:%.*]] = icmp ule ptr [[WIDE_PTR_LB6]], [[WIDE_PTR_PTR9]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP14]], label %[[LAND_RHS:.*]], label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP15]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP15]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB17:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP18]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR20:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP18]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB22:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR21]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP18]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB24:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB17]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR20]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP25:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[CMP25]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP3]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP26]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR28]], ptr [[P]], align 8 // CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 // CHECK-NEXT: store i64 0, ptr [[LEN]], align 8 -// CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED1]], i32 0, i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP6]], align 8 -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP8]], i64 1 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR5:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB7:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR6]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP3]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB9:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR8]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR5]], ptr [[P2]], align 8 -// CHECK-NEXT: [[LEN10:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED1]], i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr [[LEN10]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 0 +// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP8]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP9]], i64 1 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP34]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 1 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP34]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP12]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP35]], i32 0, i32 2 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP34]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP36]], ptr align 8 [[TMP_TMP34]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP36]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB38:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR37]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP39]], ptr align 8 [[TMP_TMP34]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR41:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB43:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR42]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP39]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB45:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR44]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST46:%.*]] = ptrtoint ptr [[WIDE_PTR_UB38]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST47:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR41]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB48:%.*]] = sub i64 [[SUB_PTR_LHS_CAST46]], [[SUB_PTR_RHS_CAST47]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_DIV49:%.*]] = sdiv exact i64 [[SUB_PTR_SUB48]], 4, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP50:%.*]] = icmp ule i64 0, [[SUB_PTR_DIV49]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP50]], label %[[CONT52:.*]], label %[[TRAP51:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP51]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT52]]: +// CHECK-NEXT: [[P53:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED33]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP54]], ptr align 8 [[TMP_TMP34]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR56:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR55]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB58:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR57]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR59:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP54]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB60:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR59]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR56]], ptr [[P53]], align 8 +// CHECK-NEXT: [[LEN61:%.*]] = getelementptr inbounds nuw [[STRUCT_COUNTED_BY]], ptr [[AGG_TMP_ENSURED33]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN61]], align 8 // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_struct_counted_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_struct_counted_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: ret void // void test_struct_counted_by(void) { @@ -935,93 +1059,200 @@ struct sized_by { size_t len; }; -// CHECK-LABEL: @test_struct_sized_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_struct_sized_by( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_SIZED_BY:%.*]], align 8 -// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TMP_ENSURED8:%.*]] = alloca [[STRUCT_SIZED_BY]], align 8 -// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP25:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP40:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED47:%.*]] = alloca [[STRUCT_SIZED_BY]], align 8 +// CHECK-NEXT: [[TMP_TMP48:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP49:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP50:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP60:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.1", align 8 +// CHECK-NEXT: [[AGG_TEMP61:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP81:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[P]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP8]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_LHS_TRUE:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_LHS_TRUE]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP21:%.*]] = icmp ule ptr [[WIDE_PTR_LB13]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP21]], label %[[LAND_RHS:.*]], label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP22]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB24:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR23]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP26]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR28:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB30:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB32:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR31]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR28]], ptr [[TMP6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB30]], ptr [[TMP7]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB32]], ptr [[TMP8]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP25]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_UB24]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR34]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP39:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[ENTRY]] ], [ [[CMP39]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP40]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR42:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR41]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB44:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR43]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP40]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB46:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR45]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR42]], ptr [[P]], align 8 // CHECK-NEXT: [[LEN:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 // CHECK-NEXT: store i64 0, ptr [[LEN]], align 8 -// CHECK-NEXT: [[P9:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 0 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP7]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP11]], i64 1 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP12]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP19]], align 8 -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[P9]], align 8 -// CHECK-NEXT: [[LEN24:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr [[LEN24]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 0 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP15]], i64 1 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 1 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP50]], i32 0, i32 2 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP21]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP49]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP48]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR52]], ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP48]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB54]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP48]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB56]], ptr [[TMP25]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP57]], ptr align 8 [[TMP_TMP48]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP57]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB59:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR58]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP61]], ptr align 8 [[TMP_TMP48]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP61]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR63:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR62]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR64:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP61]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB65:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR64]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR66:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP61]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB67:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR66]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR63]], ptr [[TMP26]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_UB65]], ptr [[TMP27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: store ptr [[WIDE_PTR_LB67]], ptr [[TMP28]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR68:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR69:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR68]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB71:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR70]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.1", ptr [[AGG_TEMP60]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB73:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR72]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_LHS_CAST74:%.*]] = ptrtoint ptr [[WIDE_PTR_UB59]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_RHS_CAST75:%.*]] = ptrtoint ptr [[WIDE_PTR_PTR69]] to i64, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[SUB_PTR_SUB76:%.*]] = sub i64 [[SUB_PTR_LHS_CAST74]], [[SUB_PTR_RHS_CAST75]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP77:%.*]] = icmp ule i64 0, [[SUB_PTR_SUB76]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP77]], label %[[CONT79:.*]], label %[[TRAP78:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP78]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT79]]: +// CHECK-NEXT: [[P80:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED47]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP81]], ptr align 8 [[TMP_TMP48]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR82:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP81]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR83:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR82]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR84:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP81]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB85:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR84]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR86:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP81]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB87:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR86]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR83]], ptr [[P80]], align 8 +// CHECK-NEXT: [[LEN88:%.*]] = getelementptr inbounds nuw [[STRUCT_SIZED_BY]], ptr [[AGG_TMP_ENSURED47]], i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr [[LEN88]], align 8 // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_struct_sized_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_struct_sized_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR3]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: ret void // void test_struct_sized_by(void) { @@ -1036,162 +1267,226 @@ struct ended_by { void *end; }; -// CHECK-LABEL: @test_struct_ended_by( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_struct_ended_by( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_ENDED_BY:%.*]], align 8 -// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP9:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TMP_ENSURED24:%.*]] = alloca [[STRUCT_ENDED_BY]], align 8 -// CHECK-NEXT: [[AGG_TEMP26:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP27:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TEMP41:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[TMP_TMP43:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[START:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP2:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP18:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP21:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP24:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP39:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED46:%.*]] = alloca [[STRUCT_ENDED_BY]], align 8 +// CHECK-NEXT: [[TMP_TMP47:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP48:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP49:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP56:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP57:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP58:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP66:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP69:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP80:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP88:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[START]], align 8 +// CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 +// CHECK-NEXT: [[UPPER4:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY3]], i64 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYDECAY3]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[UPPER4]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ARRAYDECAY3]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR6:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR5]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB8:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR7]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP2]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB10:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR9]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP1]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR6]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP1]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB8]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP1]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB10]], ptr [[TMP11]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[TMP_TMP1]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP11]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP11]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP18]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP18]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB20:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR13]], [[WIDE_PTR_UB20]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP21]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP21]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP24]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP24]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR26:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR25]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP24]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB28:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR27]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP24]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB30:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR29]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP31:%.*]] = icmp ule ptr [[WIDE_PTR_LB23]], [[WIDE_PTR_PTR26]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP12:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP31]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP12]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[START:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP32]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP32]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP32]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP32]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR34]], ptr [[START]], align 8 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 -// CHECK-NEXT: [[ARRAYDECAY10:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 -// CHECK-NEXT: [[UPPER11:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY10]], i64 0 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ARRAYDECAY10]], ptr [[TMP6]], align 8 -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[UPPER11]], ptr [[TMP7]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ARRAYDECAY10]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP9]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP10]], align 8 -// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP11]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[END]], align 8 -// CHECK-NEXT: [[START25:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED24]], i32 0, i32 0 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP13]], align 8 -// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP12]], ptr [[TMP14]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP15]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP17]], i64 1 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP20]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[TMP22]], align 8 -// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP23]], ptr [[TMP24]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR29:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR28]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB31:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR30]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP27]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB33:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR32]], align 8 -// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR29]], ptr [[TMP25]], align 8 -// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB31]], ptr [[TMP26]], align 8 -// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB33]], ptr [[TMP27]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR35:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR34]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB37:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR36]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP26]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB39:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR38]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR35]], ptr [[START25]], align 8 -// CHECK-NEXT: [[END40:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED24]], i32 0, i32 1 -// CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP29]], align 8 -// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP28]], ptr [[TMP30]], align 8 -// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP31]], align 8 -// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 0 -// CHECK-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP32]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH44:%.*]] = getelementptr i32, ptr [[TMP33]], i64 1 -// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH44]], ptr [[TMP34]], align 8 -// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 1 -// CHECK-NEXT: [[TMP36:%.*]] = load ptr, ptr [[TMP35]], align 8 -// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP36]], ptr [[TMP37]], align 8 -// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP43]], i32 0, i32 2 -// CHECK-NEXT: [[TMP39:%.*]] = load ptr, ptr [[TMP38]], align 8 -// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP39]], ptr [[TMP40]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR46:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR45]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB48:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR47]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR49:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP42]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB50:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR49]], align 8 -// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR46]], ptr [[TMP41]], align 8 -// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB48]], ptr [[TMP42]], align 8 -// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB50]], ptr [[TMP43]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR51:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR52:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR51]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR53:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB54:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR53]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR55:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP41]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB56:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR55]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR52]], ptr [[END40]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP39]], ptr align 8 [[TMP_TMP1]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP39]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR41:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR40]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP39]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB43:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR42]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP39]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB45:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR44]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR41]], ptr [[END]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP13]], ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 0 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP18]], i64 1 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 1 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP21]], ptr [[TMP22]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP49]], i32 0, i32 2 +// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[TMP23]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP24]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR50:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR51:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR50]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR52:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB53:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR52]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP48]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB55:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR54]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP47]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR51]], ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP47]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB53]], ptr [[TMP27]], align 8 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP47]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB55]], ptr [[TMP28]], align 8 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP30]], align 8 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP29]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 0 +// CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[TMP33]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH59:%.*]] = getelementptr i32, ptr [[TMP34]], i64 1 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH59]], ptr [[TMP35]], align 8 +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 1 +// CHECK-NEXT: [[TMP37:%.*]] = load ptr, ptr [[TMP36]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP37]], ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP58]], i32 0, i32 2 +// CHECK-NEXT: [[TMP40:%.*]] = load ptr, ptr [[TMP39]], align 8 +// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP40]], ptr [[TMP41]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR60:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR61:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR60]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR62:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB63:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR62]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR64:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP57]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB65:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR64]], align 8 +// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP56]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR61]], ptr [[TMP42]], align 8 +// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP56]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB63]], ptr [[TMP43]], align 8 +// CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP56]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB65]], ptr [[TMP44]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP66]], ptr align 8 [[TMP_TMP47]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR67:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP66]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB68:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR67]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP69]], ptr align 8 [[TMP_TMP47]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR70:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR71:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR70]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR72:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB73:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR72]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR74:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP69]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB75:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR74]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP76:%.*]] = icmp ule ptr [[WIDE_PTR_LB68]], [[WIDE_PTR_PTR71]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP76]], label %[[CONT78:.*]], label %[[TRAP77:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP77]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT78]]: +// CHECK-NEXT: [[START79:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED46]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP80]], ptr align 8 [[TMP_TMP47]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR81:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP80]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR82:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR81]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR83:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP80]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB84:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR83]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR85:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP80]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB86:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR85]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR82]], ptr [[START79]], align 8 +// CHECK-NEXT: [[END87:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY]], ptr [[AGG_TMP_ENSURED46]], i32 0, i32 1 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP88]], ptr align 8 [[TMP_TMP56]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR89:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR90:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR89]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR91:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB92:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR91]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR93:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP88]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB94:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR93]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR90]], ptr [[END87]], align 8 // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_struct_ended_by( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_struct_ended_by( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR3]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: ret void // void test_struct_ended_by(void) { @@ -1205,89 +1500,149 @@ struct ended_by_itself { void *__ended_by(end) end; }; -// CHECK-LABEL: @test_struct_ended_by_itself( -// CHECK-NEXT: entry: +// CHECK-LABEL: define dso_local void @test_struct_ended_by_itself( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: [[ZERO:%.*]] = alloca [0 x i32], align 4 // CHECK-NEXT: [[ONE:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_ENDED_BY_ITSELF:%.*]], align 8 -// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[AGG_TMP_ENSURED8:%.*]] = alloca [[STRUCT_ENDED_BY_ITSELF]], align 8 -// CHECK-NEXT: [[AGG_TEMP10:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 -// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 -// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: [[TMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP1:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP8:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP11:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP14:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP22:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TMP_ENSURED29:%.*]] = alloca [[STRUCT_ENDED_BY_ITSELF]], align 8 +// CHECK-NEXT: [[TMP_TMP30:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP31:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[TMP_TMP32:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8 +// CHECK-NEXT: [[AGG_TEMP39:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP42:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 +// CHECK-NEXT: [[AGG_TEMP53:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable.0", align 8 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [0 x i32], ptr [[ZERO]], i64 0, i64 0 // CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 0 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP0]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[UPPER]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[TMP2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 0 // CHECK-NEXT: [[WIDE_PTR_PTR:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 1 // CHECK-NEXT: [[WIDE_PTR_UB:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP1]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP]], i32 0, i32 2 // CHECK-NEXT: [[WIDE_PTR_LB:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR]], align 8 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 0 // CHECK-NEXT: store ptr [[WIDE_PTR_PTR]], ptr [[TMP3]], align 8 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 1 // CHECK-NEXT: store ptr [[WIDE_PTR_UB]], ptr [[TMP4]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP]], i32 0, i32 2 // CHECK-NEXT: store ptr [[WIDE_PTR_LB]], ptr [[TMP5]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR3]], ptr [[END]], align 8 -// CHECK-NEXT: [[END9:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED8]], i32 0, i32 0 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP7]], align 8 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP8]], align 8 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP9]], align 8 -// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 0 -// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8 -// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP11]], i64 1 -// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP12]], align 8 -// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 1 -// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 -// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[TMP14]], ptr [[TMP15]], align 8 -// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP]], i32 0, i32 2 -// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 -// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[TMP17]], ptr [[TMP18]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR13:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR12]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB15:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR14]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP11]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB17:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR16]], align 8 -// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR13]], ptr [[TMP19]], align 8 -// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 -// CHECK-NEXT: store ptr [[WIDE_PTR_UB15]], ptr [[TMP20]], align 8 -// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 -// CHECK-NEXT: store ptr [[WIDE_PTR_LB17]], ptr [[TMP21]], align 8 -// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR18:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 0 -// CHECK-NEXT: [[WIDE_PTR_PTR19:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR18]], align 8 -// CHECK-NEXT: [[WIDE_PTR_UB_ADDR20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 1 -// CHECK-NEXT: [[WIDE_PTR_UB21:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR20]], align 8 -// CHECK-NEXT: [[WIDE_PTR_LB_ADDR22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP10]], i32 0, i32 2 -// CHECK-NEXT: [[WIDE_PTR_LB23:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR22]], align 8 -// CHECK-NEXT: store ptr [[WIDE_PTR_PTR19]], ptr [[END9]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP1]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR2:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR3:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR2]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR4:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB5:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR4]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR6:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP1]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB7:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR6]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP8]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP8]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB10:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR9]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP:%.*]] = icmp ule ptr [[WIDE_PTR_PTR3]], [[WIDE_PTR_UB10]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_RHS]]: +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP11]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR12:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP11]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB13:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR12]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP14]], ptr align 8 [[TMP]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR15:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR16:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR15]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB18:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR17]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP14]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB20:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR19]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP21:%.*]] = icmp ule ptr [[WIDE_PTR_LB13]], [[WIDE_PTR_PTR16]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br label %[[LAND_END]], {{!annotation ![0-9]+}} +// CHECK: [[LAND_END]]: +// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ [[CMP21]], %[[LAND_RHS]] ], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[TMP6]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT]]: +// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP22]], ptr align 8 [[TMP]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR23:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP22]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR24:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR23]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR25:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP22]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB26:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR25]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR27:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP22]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB28:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR27]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR24]], ptr [[END]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr i32, ptr [[ONE]], i64 1 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[ONE]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 0 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[BOUND_PTR_ARITH:%.*]] = getelementptr i32, ptr [[TMP12]], i64 1 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[BOUND_PTR_ARITH]], ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 1 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[TMP_TMP32]], i32 0, i32 2 +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP19]], align 8 +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR33:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR34:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR33]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR35:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB36:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR35]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR37:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP31]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB38:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR37]], align 8 +// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP30]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR34]], ptr [[TMP20]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP30]], i32 0, i32 1 +// CHECK-NEXT: store ptr [[WIDE_PTR_UB36]], ptr [[TMP21]], align 8 +// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[TMP_TMP30]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[WIDE_PTR_LB38]], ptr [[TMP22]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP39]], ptr align 8 [[TMP_TMP30]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR40:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP39]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB41:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR40]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP42]], ptr align 8 [[TMP_TMP30]], i64 24, i1 false), {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR43:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 0, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_PTR44:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR43]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR45:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 1, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_UB46:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR45]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR47:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP42]], i32 0, i32 2, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[WIDE_PTR_LB48:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR47]], align 8, {{!annotation ![0-9]+}} +// CHECK-NEXT: [[CMP49:%.*]] = icmp ule ptr [[WIDE_PTR_LB41]], [[WIDE_PTR_PTR44]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[CMP49]], label %[[CONT51:.*]], label %[[TRAP50:.*]], !prof [[PROF3]], {{!annotation ![0-9]+}} +// CHECK: [[TRAP50]]: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}} +// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}} +// CHECK: [[CONT51]]: +// CHECK-NEXT: [[END52:%.*]] = getelementptr inbounds nuw [[STRUCT_ENDED_BY_ITSELF]], ptr [[AGG_TMP_ENSURED29]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP53]], ptr align 8 [[TMP_TMP30]], i64 24, i1 false) +// CHECK-NEXT: [[WIDE_PTR_PTR_ADDR54:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP53]], i32 0, i32 0 +// CHECK-NEXT: [[WIDE_PTR_PTR55:%.*]] = load ptr, ptr [[WIDE_PTR_PTR_ADDR54]], align 8 +// CHECK-NEXT: [[WIDE_PTR_UB_ADDR56:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP53]], i32 0, i32 1 +// CHECK-NEXT: [[WIDE_PTR_UB57:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR56]], align 8 +// CHECK-NEXT: [[WIDE_PTR_LB_ADDR58:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable.0", ptr [[AGG_TEMP53]], i32 0, i32 2 +// CHECK-NEXT: [[WIDE_PTR_LB59:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR58]], align 8 +// CHECK-NEXT: store ptr [[WIDE_PTR_PTR55]], ptr [[END52]], align 8 // CHECK-NEXT: ret void // -// CHECK-O2-LABEL: @test_struct_ended_by_itself( -// CHECK-O2-NEXT: entry: +// CHECK-O2-LABEL: define dso_local void @test_struct_ended_by_itself( +// CHECK-O2-SAME: ) local_unnamed_addr #[[ATTR3]] { +// CHECK-O2-NEXT: [[ENTRY:.*:]] // CHECK-O2-NEXT: ret void // void test_struct_ended_by_itself(void) { @@ -1296,3 +1651,6 @@ void test_struct_ended_by_itself(void) { (void) (struct ended_by_itself) {zero}; (void) (struct ended_by_itself) {&one + 1}; } +//. +// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1} +//. diff --git a/clang/test/BoundsSafety/Profile/flexible-array-member-checks-code-coverage.c b/clang/test/BoundsSafety/Profile/flexible-array-member-checks-code-coverage.c index 2f13fef9e416f..f0db02b64178a 100644 --- a/clang/test/BoundsSafety/Profile/flexible-array-member-checks-code-coverage.c +++ b/clang/test/BoundsSafety/Profile/flexible-array-member-checks-code-coverage.c @@ -1,6 +1,4 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --replace-value-regex "!annotation ![0-9]+" "!tbaa ![0-9]+" "!tbaa\.struct ![0-9]+" "!nosanitize ![0-9]+" "!srcloc ![0-9]+" --prefix-filecheck-ir-name TMP_ --version 3 - - // RUN: %clang_cc1 -O2 -triple x86_64 -fbounds-safety -fprofile-instrument=clang -fcoverage-mapping -emit-llvm %s -o - | FileCheck %s #include @@ -20,13 +18,13 @@ void bar(struct s *p); // CHECK-NEXT: store i64 [[TMP0]], ptr @__profc_foo, align 8 // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[SIZE]] to i64 // CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[BUF]], null, {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label [[CONT40:%.*]], label [[FLEX_BASE_NONNULL:%.*]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label [[CONT41:%.*]], label [[FLEX_BASE_NONNULL:%.*]], {{!annotation ![0-9]+}} // CHECK: flex.base.nonnull: // CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 [[IDX_EXT]] // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[BUF]], i64 4 // CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[BUF]], [[TMP1]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[DOTNOT49:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT49]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[DOTNOT51:%.*]] = icmp ugt ptr [[TMP1]], [[ADD_PTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[DOTNOT51]], {{!annotation ![0-9]+}} // CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT27:%.*]], !prof [[PROF6:![0-9]+]], {{!annotation ![0-9]+}} // CHECK: trap: // CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], {{!annotation ![0-9]+}} @@ -39,11 +37,9 @@ void bar(struct s *p); // CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[IDX_EXT]], -4, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_AVAIL_COUNT_DIV:%.*]] = ashr exact i64 [[GEPDIFF]], 2, {{!annotation ![0-9]+}} // CHECK-NEXT: [[FLEX_COUNT_INTPTR:%.*]] = zext nneg i32 [[TMP2]] to i64, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT:%.*]] = icmp ult i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], {{!annotation ![0-9]+}} -// CHECK-NEXT: [[DOTNOT50:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}} -// CHECK-NEXT: [[OR_COND52:%.*]] = or i1 [[DOTNOT50]], [[FLEX_COUNT_CHECK_NOT]], {{!annotation ![0-9]+}} -// CHECK-NEXT: br i1 [[OR_COND52]], label [[TRAP]], label [[CONT40]], !prof [[PROF17:![0-9]+]], {{!annotation ![0-9]+}} -// CHECK: cont40: +// CHECK-NEXT: [[FLEX_COUNT_CHECK_NOT_NOT:%.*]] = icmp ult i64 [[FLEX_AVAIL_COUNT_DIV]], [[FLEX_COUNT_INTPTR]], {{!annotation ![0-9]+}} +// CHECK-NEXT: br i1 [[FLEX_COUNT_CHECK_NOT_NOT]], label [[TRAP]], label [[CONT41]], !prof [[PROF17:![0-9]+]], {{!annotation ![0-9]+}} +// CHECK: cont41: // CHECK-NEXT: tail call void @bar(ptr noundef [[BUF]]) #[[ATTR4:[0-9]+]] // CHECK-NEXT: ret void // diff --git a/clang/test/BoundsSafety/Sema/SystemHeaders/bounds-checks-inline.c b/clang/test/BoundsSafety/Sema/SystemHeaders/bounds-checks-inline.c index 718e1d18cf766..5823f40f15e85 100644 --- a/clang/test/BoundsSafety/Sema/SystemHeaders/bounds-checks-inline.c +++ b/clang/test/BoundsSafety/Sema/SystemHeaders/bounds-checks-inline.c @@ -1,5 +1,3 @@ -// RUN: %clang_cc1 -fbounds-safety %s -I %S/include -verify=legacy,legacy-incorrect,common-incorrect,common +// RUN: %clang_cc1 -fbounds-safety %s -I %S/include -verify=incorrect,common-incorrect,common // RUN: %clang_cc1 -fbounds-safety %s -I %S/include -verify=strict,common -fno-bounds-safety-relaxed-system-headers -// RUN: %clang_cc1 -fbounds-safety -fbounds-safety-bringup-missing-checks=all %s -DTEST_COMPOUND_LITERALS -I %S/include -verify=incorrect,common-incorrect,common -// RUN: %clang_cc1 -fbounds-safety -fbounds-safety-bringup-missing-checks=all %s -DTEST_COMPOUND_LITERALS -I %S/include -verify=strict,common -fno-bounds-safety-relaxed-system-headers -#include +#include "bounds-checks-inline.h" diff --git a/clang/test/BoundsSafety/Sema/SystemHeaders/include/bounds-checks-inline.h b/clang/test/BoundsSafety/Sema/SystemHeaders/include/bounds-checks-inline.h index 8bfe1138a9aa1..b04ddc156104a 100644 --- a/clang/test/BoundsSafety/Sema/SystemHeaders/include/bounds-checks-inline.h +++ b/clang/test/BoundsSafety/Sema/SystemHeaders/include/bounds-checks-inline.h @@ -129,9 +129,6 @@ inline void inline_header_assign_local_cb_unsafe_ptr(void) { // strict-error@+1{{assignment to 'count2' requires corresponding assignment to 'int *__single __counted_by(count2)' (aka 'int *__single') 'local2'; add self assignment 'local2 = local2' if the value has not changed}} count2 = 0; } - -#ifdef TEST_COMPOUND_LITERALS - struct simple_cb { int count; int* __counted_by(count) ptr; @@ -158,5 +155,3 @@ inline void inline_header_compound_literal_unsafe_indexable_ptr(struct simple_cb // incorrect-error@+1{{cannot extract the lower bound of 'int *__unsafe_indexable' because it has no bounds specification}} s = (struct simple_cb){.count = 0, .ptr = unsafe_indexable_ptr}; } - -#endif diff --git a/clang/test/BoundsSafety/Sema/bounds-attributed-in-return-immutable-dependent-param.c b/clang/test/BoundsSafety/Sema/bounds-attributed-in-return-immutable-dependent-param.c index 53852622d2e19..2bab0ea9cfe7c 100644 --- a/clang/test/BoundsSafety/Sema/bounds-attributed-in-return-immutable-dependent-param.c +++ b/clang/test/BoundsSafety/Sema/bounds-attributed-in-return-immutable-dependent-param.c @@ -1,10 +1,5 @@ - -// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,legacy %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs %s #include diff --git a/clang/test/BoundsSafety/Sema/compound-literal-counted_by.c b/clang/test/BoundsSafety/Sema/compound-literal-counted_by.c index ce000936742b7..df4d7b6e01916 100644 --- a/clang/test/BoundsSafety/Sema/compound-literal-counted_by.c +++ b/clang/test/BoundsSafety/Sema/compound-literal-counted_by.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both %s #include int side_effect(void); diff --git a/clang/test/BoundsSafety/Sema/compound-literal-counted_by_or_null.c b/clang/test/BoundsSafety/Sema/compound-literal-counted_by_or_null.c index 508bd058bdc4d..ce22ec5a3893e 100644 --- a/clang/test/BoundsSafety/Sema/compound-literal-counted_by_or_null.c +++ b/clang/test/BoundsSafety/Sema/compound-literal-counted_by_or_null.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both %s #include int side_effect(void); diff --git a/clang/test/BoundsSafety/Sema/compound-literal-ended_by.c b/clang/test/BoundsSafety/Sema/compound-literal-ended_by.c index ab95be87121db..07b1f0ab23f22 100644 --- a/clang/test/BoundsSafety/Sema/compound-literal-ended_by.c +++ b/clang/test/BoundsSafety/Sema/compound-literal-ended_by.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both %s #include int side_effect(void); diff --git a/clang/test/BoundsSafety/Sema/compound-literal-sized_by.c b/clang/test/BoundsSafety/Sema/compound-literal-sized_by.c index 545114e587391..d0a4041e115dd 100644 --- a/clang/test/BoundsSafety/Sema/compound-literal-sized_by.c +++ b/clang/test/BoundsSafety/Sema/compound-literal-sized_by.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both %s #include int side_effect(void); diff --git a/clang/test/BoundsSafety/Sema/compound-literal-sized_by_or_null.c b/clang/test/BoundsSafety/Sema/compound-literal-sized_by_or_null.c index fec49814d610c..5968ea70b0802 100644 --- a/clang/test/BoundsSafety/Sema/compound-literal-sized_by_or_null.c +++ b/clang/test/BoundsSafety/Sema/compound-literal-sized_by_or_null.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without compound_literal_init (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=both %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both -fbounds-safety-bringup-missing-checks=compound_literal_init %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,both %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,both %s #include int side_effect(void); diff --git a/clang/test/BoundsSafety/Sema/counted-by-ptr-arith-constant-count.c b/clang/test/BoundsSafety/Sema/counted-by-ptr-arith-constant-count.c index dac087ae6a718..7ff67f8df4af2 100644 --- a/clang/test/BoundsSafety/Sema/counted-by-ptr-arith-constant-count.c +++ b/clang/test/BoundsSafety/Sema/counted-by-ptr-arith-constant-count.c @@ -1,7 +1,4 @@ - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=indirect_count_update -verify=expected,legacy,extra %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=compound_literal_init -verify=expected,legacy,cli %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy,extra,cli %s #include void consume_cb(int* __counted_by(3) p); diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c index 4076f36f1f48b..c54728d4920c4 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c @@ -1,9 +1,5 @@ - -// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs %s #include // Test diagnostics on _counted_by(_or_null) pointers with an incomplete struct // pointee type. diff --git a/clang/test/BoundsSafety/Sema/dynamic-count-ptr-null.c b/clang/test/BoundsSafety/Sema/dynamic-count-ptr-null.c index 195c75f86b90d..7d2af45f45143 100644 --- a/clang/test/BoundsSafety/Sema/dynamic-count-ptr-null.c +++ b/clang/test/BoundsSafety/Sema/dynamic-count-ptr-null.c @@ -1,11 +1,5 @@ - -// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,compound-literal -fbounds-safety-bringup-missing-checks=compound_literal_init %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs,compound-literal %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected,rs,compound-literal %s #include #include diff --git a/clang/test/BoundsSafety/Sema/dynamic-count-ptr-return.c b/clang/test/BoundsSafety/Sema/dynamic-count-ptr-return.c index e8e421e2dcb8b..70758eb48a23f 100644 --- a/clang/test/BoundsSafety/Sema/dynamic-count-ptr-return.c +++ b/clang/test/BoundsSafety/Sema/dynamic-count-ptr-return.c @@ -1,12 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected %s -// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=guarded %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected -fbounds-safety-bringup-missing-checks=return_size %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=guarded %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -x objective-c -fbounds-attributes-objc-experimental -verify=expected -fbounds-safety-bringup-missing-checks=return_size %s - -// guarded-no-diagnostics #include #include diff --git a/clang/test/BoundsSafety/Sema/ended_by_assignments.c b/clang/test/BoundsSafety/Sema/ended_by_assignments.c index ffecb96441ae2..8016eb2646932 100644 --- a/clang/test/BoundsSafety/Sema/ended_by_assignments.c +++ b/clang/test/BoundsSafety/Sema/ended_by_assignments.c @@ -1,8 +1,4 @@ - -// TODO: We should get the same diagnostics with/without return_size (rdar://138982703) - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs -fbounds-safety-bringup-missing-checks=return_size %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,rs %s #include int *__ended_by(end) func_ret_end(int *end) { diff --git a/clang/test/BoundsSafety/Sema/sized-by-ptr-arith-constant-count.c b/clang/test/BoundsSafety/Sema/sized-by-ptr-arith-constant-count.c index 545c3fa0f5d55..e5b9585bd52c3 100644 --- a/clang/test/BoundsSafety/Sema/sized-by-ptr-arith-constant-count.c +++ b/clang/test/BoundsSafety/Sema/sized-by-ptr-arith-constant-count.c @@ -1,7 +1,4 @@ - -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=indirect_count_update -verify=expected,legacy,extra %s -// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -fbounds-safety-bringup-missing-checks=compound_literal_init -verify=expected,legacy,cli %s +// RUN: %clang_cc1 -fsyntax-only -fbounds-safety -verify=expected,legacy,extra,cli %s #include void consume_sb(int* __sized_by(3) p); diff --git a/clang/unittests/Tooling/BoundsSafetyBringupMissingChecks.cpp b/clang/unittests/Tooling/BoundsSafetyBringupMissingChecks.cpp index 83687ebb7ce3c..9b97d6296d75a 100644 --- a/clang/unittests/Tooling/BoundsSafetyBringupMissingChecks.cpp +++ b/clang/unittests/Tooling/BoundsSafetyBringupMissingChecks.cpp @@ -205,6 +205,10 @@ TEST(BoundsSafetyBringUpMissingChecks, DefaultWithBoundsSafety) { {NEED_CC1_ARG "-fbounds-safety"}, [](LangOptions &LO) { EXPECT_EQ(LO.BoundsSafetyBringUpMissingChecks, LangOptions::getDefaultBoundsSafetyNewChecksMask()); + + // "batch_0" is the default. + EXPECT_EQ(LO.BoundsSafetyBringUpMissingChecks, + LangOptions::getBoundsSafetyNewChecksMaskForGroup("batch_0")); }); ASSERT_TRUE(Result); }