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