Author: Alex Richardson
Date: 2020-06-18T18:09:21+01:00
New Revision: 3ce0e92f45f56fc1b93db35dec8c53dceb5c54a5

URL: 
https://github.com/llvm/llvm-project/commit/3ce0e92f45f56fc1b93db35dec8c53dceb5c54a5
DIFF: 
https://github.com/llvm/llvm-project/commit/3ce0e92f45f56fc1b93db35dec8c53dceb5c54a5.diff

LOG: [update_cc_test_checks.py] Handle C++ methods

Previously the script only handled C input, this change extends the JSON
parsing to to also include C++ function types such as methods, constructors
and destructors.

Reviewed By: MaskRay
Differential Revision: https://reviews.llvm.org/D80914

Added: 
    clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp
    clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
    clang/test/utils/update_cc_test_checks/basic-cplusplus.test

Modified: 
    llvm/utils/update_cc_test_checks.py

Removed: 
    


################################################################################
diff  --git a/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp 
b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp
new file mode 100644
index 000000000000..98be350b3937
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp
@@ -0,0 +1,25 @@
+// Basic C++ test for update_cc_test_checks
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
+
+class Foo {
+  int x;
+
+public:
+  explicit Foo(int x);
+  ~Foo();
+  inline int function_defined_inline(int arg) const {
+    return arg + x;
+  }
+  inline int function_defined_out_of_line(int arg) const;
+};
+
+Foo::Foo(int x) : x(x) {}
+Foo::~Foo() {}
+int Foo::function_defined_out_of_line(int arg) const { return x - arg; }
+
+// Call the inline methods to ensure the LLVM IR is generated:
+int main() {
+  Foo f(1);
+  f.function_defined_inline(2);
+  f.function_defined_out_of_line(3);
+}

diff  --git 
a/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected 
b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
new file mode 100644
index 000000000000..48ee67a7165a
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
@@ -0,0 +1,80 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// Basic C++ test for update_cc_test_checks
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
+
+class Foo {
+  int x;
+
+public:
+  explicit Foo(int x);
+  ~Foo();
+// CHECK-LABEL: @_ZNK3Foo23function_defined_inlineEi(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8
+// CHECK-NEXT:    [[ARG_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], 
align 8
+// CHECK-NEXT:    store i32 [[ARG:%.*]], i32* [[ARG_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load %class.Foo*, %class.Foo** 
[[THIS_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARG_ADDR]], align 4
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], 
%class.Foo* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[X]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    ret i32 [[ADD]]
+//
+  inline int function_defined_inline(int arg) const {
+    return arg + x;
+  }
+  inline int function_defined_out_of_line(int arg) const;
+};
+
+// CHECK-LABEL: @_ZN3FooC1Ei(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], 
align 8
+// CHECK-NEXT:    store i32 [[X:%.*]], i32* [[X_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load %class.Foo*, %class.Foo** 
[[THIS_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4
+// CHECK-NEXT:    call void @_ZN3FooC2Ei(%class.Foo* [[THIS1]], i32 [[TMP0]])
+// CHECK-NEXT:    ret void
+//
+Foo::Foo(int x) : x(x) {}
+// CHECK-LABEL: @_ZN3FooD1Ev(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8
+// CHECK-NEXT:    store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], 
align 8
+// CHECK-NEXT:    [[THIS1:%.*]] = load %class.Foo*, %class.Foo** 
[[THIS_ADDR]], align 8
+// CHECK-NEXT:    call void @_ZN3FooD2Ev(%class.Foo* [[THIS1]]) #2
+// CHECK-NEXT:    ret void
+//
+Foo::~Foo() {}
+// CHECK-LABEL: @_ZNK3Foo28function_defined_out_of_lineEi(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8
+// CHECK-NEXT:    [[ARG_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], 
align 8
+// CHECK-NEXT:    store i32 [[ARG:%.*]], i32* [[ARG_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load %class.Foo*, %class.Foo** 
[[THIS_ADDR]], align 8
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], 
%class.Foo* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[X]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARG_ADDR]], align 4
+// CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    ret i32 [[SUB]]
+//
+int Foo::function_defined_out_of_line(int arg) const { return x - arg; }
+
+// Call the inline methods to ensure the LLVM IR is generated:
+// CHECK-LABEL: @main(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
+// CHECK-NEXT:    call void @_ZN3FooC1Ei(%class.Foo* [[F]], i32 1)
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 
@_ZNK3Foo23function_defined_inlineEi(%class.Foo* [[F]], i32 2)
+// CHECK-NEXT:    [[CALL1:%.*]] = call i32 
@_ZNK3Foo28function_defined_out_of_lineEi(%class.Foo* [[F]], i32 3)
+// CHECK-NEXT:    call void @_ZN3FooD1Ev(%class.Foo* [[F]]) #2
+// CHECK-NEXT:    ret i32 0
+//
+int main() {
+  Foo f(1);
+  f.function_defined_inline(2);
+  f.function_defined_out_of_line(3);
+}

diff  --git a/clang/test/utils/update_cc_test_checks/basic-cplusplus.test 
b/clang/test/utils/update_cc_test_checks/basic-cplusplus.test
new file mode 100644
index 000000000000..10be017388c6
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/basic-cplusplus.test
@@ -0,0 +1,7 @@
+## Test that CHECK lines are generated before the definion and not the 
declaration
+
+# RUN: cp %S/Inputs/basic-cplusplus.cpp %t.cpp && %update_cc_test_checks %t.cpp
+# RUN: 
diff  -u %S/Inputs/basic-cplusplus.cpp.expected %t.cpp
+## Check that re-running update_cc_test_checks doesn't change the output
+# RUN: %update_cc_test_checks %t.cpp
+# RUN: 
diff  -u %S/Inputs/basic-cplusplus.cpp.expected %t.cpp

diff  --git a/llvm/utils/update_cc_test_checks.py 
b/llvm/utils/update_cc_test_checks.py
index 127d3d737576..7c69ff339cfb 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -61,11 +61,14 @@ def get_line2spell_and_mangled(args, clang_args):
   def parse_clang_ast_json(node):
     node_kind = node['kind']
     # Recurse for the following nodes that can contain nested function decls:
-    if node_kind in ('NamespaceDecl', 'LinkageSpecDecl', 
'TranslationUnitDecl'):
-      for inner in node['inner']:
-        parse_clang_ast_json(inner)
+    if node_kind in ('NamespaceDecl', 'LinkageSpecDecl', 'TranslationUnitDecl',
+                     'CXXRecordDecl'):
+      if 'inner' in node:
+        for inner in node['inner']:
+          parse_clang_ast_json(inner)
     # Otherwise we ignore everything except functions:
-    if node['kind'] != 'FunctionDecl':
+    if node_kind not in ('FunctionDecl', 'CXXMethodDecl', 'CXXConstructorDecl',
+                         'CXXDestructorDecl', 'CXXConversionDecl'):
       return
     if node.get('isImplicit') is True and node.get('storageClass') == 'extern':
       common.debug('Skipping builtin function:', node['name'], '@', 
node['loc'])


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to