13ce0e92fSAlex Richardson// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 23ce0e92fSAlex Richardson// Basic C++ test for update_cc_test_checks 3*b16a3b4fSNikita Popov// RUN: %clang_cc1 -no-opaque-pointers -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s 43ce0e92fSAlex Richardson 53ce0e92fSAlex Richardsonclass Foo { 63ce0e92fSAlex Richardson int x; 73ce0e92fSAlex Richardson 83ce0e92fSAlex Richardsonpublic: 93ce0e92fSAlex Richardson explicit Foo(int x); 103ce0e92fSAlex Richardson ~Foo(); 113ce0e92fSAlex Richardson// CHECK-LABEL: @_ZNK3Foo23function_defined_inlineEi( 123ce0e92fSAlex Richardson// CHECK-NEXT: entry: 133ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8 143ce0e92fSAlex Richardson// CHECK-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4 153ce0e92fSAlex Richardson// CHECK-NEXT: store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], align 8 163ce0e92fSAlex Richardson// CHECK-NEXT: store i32 [[ARG:%.*]], i32* [[ARG_ADDR]], align 4 173ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS1:%.*]] = load %class.Foo*, %class.Foo** [[THIS_ADDR]], align 8 183ce0e92fSAlex Richardson// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARG_ADDR]], align 4 193ce0e92fSAlex Richardson// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], %class.Foo* [[THIS1]], i32 0, i32 0 203ce0e92fSAlex Richardson// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[X]], align 4 213ce0e92fSAlex Richardson// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] 223ce0e92fSAlex Richardson// CHECK-NEXT: ret i32 [[ADD]] 233ce0e92fSAlex Richardson// 243ce0e92fSAlex Richardson inline int function_defined_inline(int arg) const { 253ce0e92fSAlex Richardson return arg + x; 263ce0e92fSAlex Richardson } 273ce0e92fSAlex Richardson inline int function_defined_out_of_line(int arg) const; 283ce0e92fSAlex Richardson}; 293ce0e92fSAlex Richardson 303ce0e92fSAlex Richardson// CHECK-LABEL: @_ZN3FooC1Ei( 313ce0e92fSAlex Richardson// CHECK-NEXT: entry: 323ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8 333ce0e92fSAlex Richardson// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 343ce0e92fSAlex Richardson// CHECK-NEXT: store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], align 8 353ce0e92fSAlex Richardson// CHECK-NEXT: store i32 [[X:%.*]], i32* [[X_ADDR]], align 4 363ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS1:%.*]] = load %class.Foo*, %class.Foo** [[THIS_ADDR]], align 8 373ce0e92fSAlex Richardson// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 3867aa314bSFlorian Hahn// CHECK-NEXT: call void @_ZN3FooC2Ei(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]]) 393ce0e92fSAlex Richardson// CHECK-NEXT: ret void 403ce0e92fSAlex Richardson// 413ce0e92fSAlex RichardsonFoo::Foo(int x) : x(x) {} 423ce0e92fSAlex Richardson// CHECK-LABEL: @_ZN3FooD1Ev( 433ce0e92fSAlex Richardson// CHECK-NEXT: entry: 443ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8 453ce0e92fSAlex Richardson// CHECK-NEXT: store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], align 8 463ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS1:%.*]] = load %class.Foo*, %class.Foo** [[THIS_ADDR]], align 8 4767aa314bSFlorian Hahn// CHECK-NEXT: call void @_ZN3FooD2Ev(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3:[0-9]+]] 483ce0e92fSAlex Richardson// CHECK-NEXT: ret void 493ce0e92fSAlex Richardson// 503ce0e92fSAlex RichardsonFoo::~Foo() {} 513ce0e92fSAlex Richardson// CHECK-LABEL: @_ZNK3Foo28function_defined_out_of_lineEi( 523ce0e92fSAlex Richardson// CHECK-NEXT: entry: 533ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8 543ce0e92fSAlex Richardson// CHECK-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4 553ce0e92fSAlex Richardson// CHECK-NEXT: store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], align 8 563ce0e92fSAlex Richardson// CHECK-NEXT: store i32 [[ARG:%.*]], i32* [[ARG_ADDR]], align 4 573ce0e92fSAlex Richardson// CHECK-NEXT: [[THIS1:%.*]] = load %class.Foo*, %class.Foo** [[THIS_ADDR]], align 8 583ce0e92fSAlex Richardson// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], %class.Foo* [[THIS1]], i32 0, i32 0 593ce0e92fSAlex Richardson// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[X]], align 4 603ce0e92fSAlex Richardson// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARG_ADDR]], align 4 613ce0e92fSAlex Richardson// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP0]], [[TMP1]] 623ce0e92fSAlex Richardson// CHECK-NEXT: ret i32 [[SUB]] 633ce0e92fSAlex Richardson// 643ce0e92fSAlex Richardsonint Foo::function_defined_out_of_line(int arg) const { return x - arg; } 653ce0e92fSAlex Richardson 663ce0e92fSAlex Richardson// Call the inline methods to ensure the LLVM IR is generated: 673ce0e92fSAlex Richardson// CHECK-LABEL: @main( 683ce0e92fSAlex Richardson// CHECK-NEXT: entry: 693ce0e92fSAlex Richardson// CHECK-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4 7067aa314bSFlorian Hahn// CHECK-NEXT: call void @_ZN3FooC1Ei(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1) 7167aa314bSFlorian Hahn// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2) 7267aa314bSFlorian Hahn// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3) 7367aa314bSFlorian Hahn// CHECK-NEXT: call void @_ZN3FooD1Ev(%class.Foo* noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR3]] 743ce0e92fSAlex Richardson// CHECK-NEXT: ret i32 0 753ce0e92fSAlex Richardson// 763ce0e92fSAlex Richardsonint main() { 773ce0e92fSAlex Richardson Foo f(1); 783ce0e92fSAlex Richardson f.function_defined_inline(2); 793ce0e92fSAlex Richardson f.function_defined_out_of_line(3); 803ce0e92fSAlex Richardson} 81