Restore test files accidentally deleted in r354839
authorReid Kleckner <rnk@google.com>
Tue, 14 May 2019 18:51:07 +0000 (18:51 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 14 May 2019 18:51:07 +0000 (18:51 +0000)
I think there must be a bug in git-llvm causing parent directories to be
deleted when the diff deletes files in a subdirectory. Perhaps it is
Windows-only.

There has been a behavior change, so some of these tests now fail. I
have marked them XFAIL and will fix them in a follow-up to separate the
changes.

llvm-svn: 360699

75 files changed:
clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp [new file with mode: 0644]
clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp [new file with mode: 0644]
clang/test/ASTMerge/anonymous-fields/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/asm/Inputs/asm-function.cpp [new file with mode: 0644]
clang/test/ASTMerge/asm/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/category/Inputs/category1.m [new file with mode: 0644]
clang/test/ASTMerge/category/Inputs/category2.m [new file with mode: 0644]
clang/test/ASTMerge/category/test.m [new file with mode: 0644]
clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp [new file with mode: 0644]
clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp [new file with mode: 0644]
clang/test/ASTMerge/class-template-partial-spec/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/class-template/Inputs/class-template1.cpp [new file with mode: 0644]
clang/test/ASTMerge/class-template/Inputs/class-template2.cpp [new file with mode: 0644]
clang/test/ASTMerge/class-template/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/class/Inputs/class1.cpp [new file with mode: 0644]
clang/test/ASTMerge/class/Inputs/class2.cpp [new file with mode: 0644]
clang/test/ASTMerge/class/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/class2/Inputs/class3.cpp [new file with mode: 0644]
clang/test/ASTMerge/class2/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/codegen-body/Inputs/body1.c [new file with mode: 0644]
clang/test/ASTMerge/codegen-body/Inputs/body2.c [new file with mode: 0644]
clang/test/ASTMerge/codegen-body/test.c [new file with mode: 0644]
clang/test/ASTMerge/codegen-exprs/Inputs/exprs1.c [new file with mode: 0644]
clang/test/ASTMerge/codegen-exprs/Inputs/exprs2.c [new file with mode: 0644]
clang/test/ASTMerge/codegen-exprs/test.c [new file with mode: 0644]
clang/test/ASTMerge/enum/Inputs/enum1.c [new file with mode: 0644]
clang/test/ASTMerge/enum/Inputs/enum2.c [new file with mode: 0644]
clang/test/ASTMerge/enum/test.c [new file with mode: 0644]
clang/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp [new file with mode: 0644]
clang/test/ASTMerge/exprs-cpp/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/exprs/Inputs/exprs1.c [new file with mode: 0644]
clang/test/ASTMerge/exprs/Inputs/exprs2.c [new file with mode: 0644]
clang/test/ASTMerge/exprs/test.c [new file with mode: 0644]
clang/test/ASTMerge/function-cpp/Inputs/function-1.cpp [new file with mode: 0644]
clang/test/ASTMerge/function-cpp/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/function/Inputs/function1.c [new file with mode: 0644]
clang/test/ASTMerge/function/Inputs/function2.c [new file with mode: 0644]
clang/test/ASTMerge/function/test.c [new file with mode: 0644]
clang/test/ASTMerge/inheritance/Inputs/inheritance-base.cpp [new file with mode: 0644]
clang/test/ASTMerge/inheritance/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp [new file with mode: 0644]
clang/test/ASTMerge/init-ctors/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp [new file with mode: 0644]
clang/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp [new file with mode: 0644]
clang/test/ASTMerge/injected-class-name-decl/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/interface/Inputs/interface1.m [new file with mode: 0644]
clang/test/ASTMerge/interface/Inputs/interface2.m [new file with mode: 0644]
clang/test/ASTMerge/interface/test.m [new file with mode: 0644]
clang/test/ASTMerge/macro/Inputs/macro.modulemap [new file with mode: 0644]
clang/test/ASTMerge/macro/Inputs/macro1.h [new file with mode: 0644]
clang/test/ASTMerge/macro/Inputs/macro1.m [new file with mode: 0644]
clang/test/ASTMerge/macro/Inputs/macro2.m [new file with mode: 0644]
clang/test/ASTMerge/macro/test.m [new file with mode: 0644]
clang/test/ASTMerge/namespace/Inputs/namespace1.cpp [new file with mode: 0644]
clang/test/ASTMerge/namespace/Inputs/namespace2.cpp [new file with mode: 0644]
clang/test/ASTMerge/namespace/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/property/Inputs/property1.m [new file with mode: 0644]
clang/test/ASTMerge/property/Inputs/property2.m [new file with mode: 0644]
clang/test/ASTMerge/property/test.m [new file with mode: 0644]
clang/test/ASTMerge/std-initializer-list/Inputs/il.cpp [new file with mode: 0644]
clang/test/ASTMerge/std-initializer-list/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/struct/Inputs/struct1.c [new file with mode: 0644]
clang/test/ASTMerge/struct/Inputs/struct2.c [new file with mode: 0644]
clang/test/ASTMerge/struct/test.c [new file with mode: 0644]
clang/test/ASTMerge/typedef/Inputs/typedef1.c [new file with mode: 0644]
clang/test/ASTMerge/typedef/Inputs/typedef2.c [new file with mode: 0644]
clang/test/ASTMerge/typedef/test.c [new file with mode: 0644]
clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp [new file with mode: 0644]
clang/test/ASTMerge/unnamed_fields/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/var-cpp/Inputs/var1.cpp [new file with mode: 0644]
clang/test/ASTMerge/var-cpp/test.cpp [new file with mode: 0644]
clang/test/ASTMerge/var/Inputs/var1.c [new file with mode: 0644]
clang/test/ASTMerge/var/Inputs/var1.h [new file with mode: 0644]
clang/test/ASTMerge/var/Inputs/var2.c [new file with mode: 0644]
clang/test/ASTMerge/var/test.c [new file with mode: 0644]

diff --git a/clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp b/clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp
new file mode 100644 (file)
index 0000000..829bc0e
--- /dev/null
@@ -0,0 +1,5 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
diff --git a/clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp b/clang/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp
new file mode 100644 (file)
index 0000000..28ea46d
--- /dev/null
@@ -0,0 +1,9 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
+
+inline int useA(A &a) {
+  return (a.f.foo + a.g.foo);
+}
diff --git a/clang/test/ASTMerge/anonymous-fields/test.cpp b/clang/test/ASTMerge/anonymous-fields/test.cpp
new file mode 100644 (file)
index 0000000..67afc29
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/anonymous-fields1.cpp
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/anonymous-fields2.cpp
+// RUN: %clang_cc1 -emit-obj -o /dev/null -ast-merge %t.1.ast -ast-merge %t.2.ast %s
+// expected-no-diagnostics
diff --git a/clang/test/ASTMerge/asm/Inputs/asm-function.cpp b/clang/test/ASTMerge/asm/Inputs/asm-function.cpp
new file mode 100644 (file)
index 0000000..1b87833
--- /dev/null
@@ -0,0 +1,21 @@
+
+unsigned char asmFunc(unsigned char a, unsigned char b) {
+  unsigned int la = a;
+  unsigned int lb = b;
+  unsigned int bigres;
+  unsigned char res;
+  __asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) :
+                        "edx", "cc");
+  res = bigres;
+  return res;
+}
+
+int asmFunc2(int i) {
+  int res;
+  asm ("mov %1, %0 \t\n"
+       "inc %0 "
+      : "=r" (res)
+      : "r" (i)
+      : "cc");
+  return res;
+}
diff --git a/clang/test/ASTMerge/asm/test.cpp b/clang/test/ASTMerge/asm/test.cpp
new file mode 100644 (file)
index 0000000..8c3bdfe
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/asm-function.cpp
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+void testAsmImport() {
+  asmFunc(12, 42);
+  asmFunc2(42);
+}
diff --git a/clang/test/ASTMerge/category/Inputs/category1.m b/clang/test/ASTMerge/category/Inputs/category1.m
new file mode 100644 (file)
index 0000000..afcaab8
--- /dev/null
@@ -0,0 +1,48 @@
+@interface I1 
+@end
+
+// Matching category
+@interface I1 (Cat1)
+- (int)method0;
+@end
+
+// Matching class extension
+@interface I1 ()
+- (int)method1;
+@end
+
+// Mismatched category
+@interface I1 (Cat2)
+- (int)method2;
+@end
+
+@interface I2
+@end
+
+// Mismatched class extension
+@interface I2 ()
+- (int)method3;
+@end
+
+// Category with implementation
+@interface I2 (Cat3)
+@end
+
+@implementation I2 (Cat3)
+@end
+
+// Category with implementation
+@interface I2 (Cat4)
+@end
+
+@implementation I2 (Cat4)
+@end
+
+// Category with mismatched implementation
+@interface I2 (Cat6)
+@end
+
+@implementation I2 (Cat6)
+- (float)blah { return 0; }
+@end
+
diff --git a/clang/test/ASTMerge/category/Inputs/category2.m b/clang/test/ASTMerge/category/Inputs/category2.m
new file mode 100644 (file)
index 0000000..49a3c27
--- /dev/null
@@ -0,0 +1,49 @@
+typedef int Int;
+
+@interface I1 
+@end
+
+// Matching category
+@interface I1 (Cat1)
+- (Int)method0;
+@end
+
+// Matching class extension
+@interface I1 ()
+- (Int)method1;
+@end
+
+// Mismatched category
+@interface I1 (Cat2)
+- (float)method2;
+@end
+
+@interface I2
+@end
+
+// Mismatched class extension
+@interface I2 ()
+- (float)method3;
+@end
+
+// Category with implementation
+@interface I2 (Cat3)
+@end
+
+@implementation I2 (Cat3)
+@end
+
+// Category with implementation
+@interface I2 (Cat5)
+@end
+
+@implementation I2 (Cat5)
+@end
+
+// Category with mismatched implementation
+@interface I2 (Cat6)
+@end
+
+@implementation I2 (Cat6)
+- (int)blah { return 0; }
+@end
diff --git a/clang/test/ASTMerge/category/test.m b/clang/test/ASTMerge/category/test.m
new file mode 100644 (file)
index 0000000..bee72f6
--- /dev/null
@@ -0,0 +1,13 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/category1.m
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/category2.m
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: category2.m:18:1: error: instance method 'method2' has incompatible result types in different translation units ('float' vs. 'int')
+// CHECK: category1.m:16:1: note: instance method 'method2' also declared here
+// CHECK: category2.m:26:1: error: instance method 'method3' has incompatible result types in different translation units ('float' vs. 'int')
+// CHECK: category1.m:24:1: note: instance method 'method3' also declared here
+// CHECK: category2.m:48:1: error: instance method 'blah' has incompatible result types in different translation units ('int' vs. 'float')
+// CHECK: category1.m:46:1: note: instance method 'blah' also declared here
+// CHECK: 3 errors generated.
diff --git a/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp b/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp
new file mode 100644 (file)
index 0000000..43606d4
--- /dev/null
@@ -0,0 +1,118 @@
+template<typename T, class P>
+struct TwoOptionTemplate {};
+
+template<typename T>
+struct TwoOptionTemplate<T, char> {
+  int member;
+};
+
+
+template<typename T>
+struct TwoOptionTemplate<T, double> {
+  float member;
+};
+
+template<typename T>
+struct TwoOptionTemplate<T, T> {
+  T** member;
+};
+
+TwoOptionTemplate<int, char> X0;
+TwoOptionTemplate<int, float> X1;
+TwoOptionTemplate<void *, wchar_t> X2;
+TwoOptionTemplate<long, long> X3;
+TwoOptionTemplate<float, float> X4;
+TwoOptionTemplate<long, long> SingleSource;
+TwoOptionTemplate<char, double> SecondDoubleSource;
+
+
+template<int I, class C>
+struct IntTemplateSpec {};
+
+template<class C>
+struct IntTemplateSpec<4, C> {
+  C member;
+};
+
+template<int I>
+struct IntTemplateSpec<I, void *> {
+  int member;
+  static constexpr int val = I;
+};
+
+template<int I>
+struct IntTemplateSpec<I, double> {
+  char member;
+  static constexpr int val = I;
+};
+
+IntTemplateSpec<4, wchar_t> Y0;
+IntTemplateSpec<5, void *> Y1;
+IntTemplateSpec<1, long> Y2;
+IntTemplateSpec<3, int> Y3;
+//template<int I> constexpr int IntTemplateSpec<I, double>::val;
+IntTemplateSpec<42, double> NumberSource;
+static_assert(NumberSource.val == 42);
+
+namespace One {
+namespace Two {
+  // Just an empty namespace to ensure we can deal with multiple namespace decls.
+}
+}
+
+
+namespace One {
+namespace Two {
+namespace Three {
+
+template<class T>
+class Parent {};
+
+} // namespace Three
+
+} // namespace Two
+
+template<typename T, typename X>
+struct Child1: public Two::Three::Parent<unsigned> {
+  char member;
+};
+
+template<class T>
+struct Child1<T, One::Two::Three::Parent<T>> {
+  T member;
+};
+
+} // namespace One
+
+One::Child1<int, double> Z0Source;
+
+// Test import of nested namespace specifiers
+template<typename T>
+struct Outer {
+  template<typename U> class Inner0;
+};
+
+template<typename X>
+template<typename Y>
+class Outer<X>::Inner0 {
+public:
+  void f(X, Y);
+  template<typename Z> struct Inner1;
+};
+
+template<typename X>
+template<typename Y>
+void Outer<X>::Inner0<Y>::f(X, Y) {}
+
+template<typename X>
+template<typename Y>
+template<typename Z>
+class Outer<X>::Inner0<Y>::Inner1 {
+public:
+  void f(Y, Z);
+};
+
+template<typename X>
+template<typename Y>
+template<typename Z>
+void Outer<X>::Inner0<Y>::Inner1<Z>::f(Y, Z) {}
diff --git a/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp b/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp
new file mode 100644 (file)
index 0000000..2f3f0c6
--- /dev/null
@@ -0,0 +1,79 @@
+template<typename T, typename P>
+struct TwoOptionTemplate {};
+
+template<typename T>
+struct TwoOptionTemplate<T, char> {
+  int member;
+};
+
+
+template<typename T>
+struct TwoOptionTemplate<T, double> {
+  float member;
+};
+
+template<typename T>
+struct TwoOptionTemplate<T, T> {
+  T** member;
+};
+
+TwoOptionTemplate<int, char> X0;
+TwoOptionTemplate<int, double> X1;
+TwoOptionTemplate<void *, wchar_t> X2;
+TwoOptionTemplate<long, long> X3;
+TwoOptionTemplate<int, int> X4;
+TwoOptionTemplate<long, long> SingleDest;
+TwoOptionTemplate<int, double> SecondDoubleDest;
+
+
+template<int I, class C>
+struct IntTemplateSpec {};
+
+template<class C>
+struct IntTemplateSpec<4, C> {
+  C member;
+};
+
+template<int I>
+struct IntTemplateSpec<I, void *> {
+  double member;
+  static constexpr int val = I;
+};
+
+template<int I>
+struct IntTemplateSpec<I, double> {
+  char member;
+  static constexpr int val = I;
+};
+
+IntTemplateSpec<4, wchar_t>Y0;
+IntTemplateSpec<5, void *> Y1;
+IntTemplateSpec<1, int> Y2;
+IntTemplateSpec<2, int> Y3;
+IntTemplateSpec<43, double> NumberDest;
+
+namespace One {
+namespace Two {
+namespace Three {
+
+template<class T>
+class Parent {};
+
+} // namespace Three
+
+} // namespace Two
+
+template<typename T, typename X>
+struct Child1: public Two::Three::Parent<unsigned> {
+  char member;
+};
+
+template<class T>
+struct Child1<T, One::Two::Three::Parent<T>> {
+  T member;
+};
+
+} // namespace One
+
+namespace Dst { One::Child1<double, One::Two::Three::Parent<double>> Z0Dst; }
+One::Child1<int, float> Z1;
diff --git a/clang/test/ASTMerge/class-template-partial-spec/test.cpp b/clang/test/ASTMerge/class-template-partial-spec/test.cpp
new file mode 100644 (file)
index 0000000..9aa4ab5
--- /dev/null
@@ -0,0 +1,27 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.1.ast %S/Inputs/class-template-partial-spec1.cpp
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.2.ast %S/Inputs/class-template-partial-spec2.cpp
+// RUN: not %clang_cc1 -std=c++1z -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+static_assert(sizeof(**SingleSource.member) == sizeof(**SingleDest.member));
+static_assert(sizeof(SecondDoubleSource.member) == sizeof(SecondDoubleDest.member));
+static_assert(NumberSource.val == 42);
+static_assert(sizeof(Z0Source.member) == sizeof(char));
+static_assert(sizeof(Dst::Z0Dst.member) == sizeof(double));
+static_assert(sizeof(One::Child1<double, One::Two::Three::Parent<double>>::member) == sizeof(double));
+
+// CHECK: class-template-partial-spec2.cpp:21:32: error: external variable 'X1' declared with incompatible types in different translation units ('TwoOptionTemplate<int, double>' vs. 'TwoOptionTemplate<int, float>')
+// CHECK: class-template-partial-spec1.cpp:21:31: note: declared here with type 'TwoOptionTemplate<int, float>'
+
+// CHECK: class-template-partial-spec2.cpp:24:29: error: external variable 'X4' declared with incompatible types in different translation units ('TwoOptionTemplate<int, int>' vs. 'TwoOptionTemplate<float, float>')
+// CHECK: class-template-partial-spec1.cpp:24:33: note: declared here with type 'TwoOptionTemplate<float, float>'
+
+// CHECK: class-template-partial-spec1.cpp:38:8: warning: type 'IntTemplateSpec<5, void *>' has incompatible definitions in different translation units
+// CHECK: class-template-partial-spec1.cpp:39:7: note: field 'member' has type 'int' here
+// CHECK: class-template-partial-spec2.cpp:39:10: note: field 'member' has type 'double' here
+
+// CHECK: class-template-partial-spec2.cpp:52:25: error: external variable 'Y3' declared with incompatible types in different translation units ('IntTemplateSpec<2, int>' vs. 'IntTemplateSpec<3, int>')
+// CHECK: class-template-partial-spec1.cpp:52:25: note: declared here with type 'IntTemplateSpec<3, int>'
+
+// CHECK-NOT: static_assert
diff --git a/clang/test/ASTMerge/class-template/Inputs/class-template1.cpp b/clang/test/ASTMerge/class-template/Inputs/class-template1.cpp
new file mode 100644 (file)
index 0000000..fb5b229
--- /dev/null
@@ -0,0 +1,37 @@
+template<typename T>
+struct X0 {
+  T getValue(T arg) { return arg; }
+};
+
+template<int I>
+struct X1;
+
+template<int I>
+struct X2;
+
+template<int I>
+struct X3;
+
+template<template<int I> class>
+struct X4;
+
+template<template<long> class>
+struct X5;
+
+template<typename>
+struct X6;
+
+extern X0<int> *x0i;
+extern X0<long> *x0l;
+extern X0<float> *x0r;
+
+template<>
+struct X0<char> {
+  int member;
+  char getValue(char ch) { return static_cast<char>(member); }
+};
+
+template<>
+struct X0<wchar_t> {
+  int member;
+};
diff --git a/clang/test/ASTMerge/class-template/Inputs/class-template2.cpp b/clang/test/ASTMerge/class-template/Inputs/class-template2.cpp
new file mode 100644 (file)
index 0000000..b5d0add
--- /dev/null
@@ -0,0 +1,37 @@
+template<class T>
+struct X0 {
+  T getValue(T arg);
+};
+
+template<int I>
+struct X1;
+
+template<long I>
+struct X2;
+
+template<typename>
+struct X3;
+
+template<template<int I> class>
+struct X4;
+
+template<template<int I> class>
+struct X5;
+
+template<template<int I> class>
+struct X6;
+
+typedef int Integer;
+extern X0<Integer> *x0i;
+extern X0<float> *x0f;
+extern X0<double> *x0r;
+
+template<>
+struct X0<char> {
+  int member;
+};
+
+template<>
+struct X0<wchar_t> {
+  float member;
+};
diff --git a/clang/test/ASTMerge/class-template/test.cpp b/clang/test/ASTMerge/class-template/test.cpp
new file mode 100644 (file)
index 0000000..f2ac4c5
--- /dev/null
@@ -0,0 +1,30 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class-template1.cpp
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.2.ast %S/Inputs/class-template2.cpp
+// RUN: not %clang_cc1 -std=c++1z  -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+static_assert(sizeof(X0<char>().getValue(1)) == sizeof(char));
+static_assert(sizeof(X0<int>().getValue(1)) == sizeof(int));
+
+// CHECK: class-template1.cpp:9:14: error: non-type template parameter declared with incompatible types in different translation units ('int' vs. 'long')
+// CHECK: class-template2.cpp:9:15: note: declared here with type 'long'
+
+// CHECK: class-template1.cpp:12:14: error: template parameter has different kinds in different translation units
+// CHECK: class-template2.cpp:12:10: note: template parameter declared here
+
+// CHECK: class-template1.cpp:18:23: error: non-type template parameter declared with incompatible types in different translation units ('long' vs. 'int')
+// CHECK: class-template2.cpp:18:23: note: declared here with type 'int'
+
+// CHECK: class-template1.cpp:21:10: error: template parameter has different kinds in different translation units
+// CHECK: class-template2.cpp:21:10: note: template parameter declared here
+
+// CHECK: class-template2.cpp:27:20: error: external variable 'x0r' declared with incompatible types in different translation units ('X0<double> *' vs. 'X0<float> *')
+// CHECK: class-template1.cpp:26:19: note: declared here with type 'X0<float> *'
+
+// CHECK: class-template1.cpp:35:8: warning: type 'X0<wchar_t>' has incompatible definitions in different translation units
+// CHECK: class-template1.cpp:36:7: note: field 'member' has type 'int' here
+// CHECK: class-template2.cpp:36:9: note: field 'member' has type 'float' here
+
+// CHECK: 1 warning and 5 errors generated.
+// CHECK-NOT: static_assert
diff --git a/clang/test/ASTMerge/class/Inputs/class1.cpp b/clang/test/ASTMerge/class/Inputs/class1.cpp
new file mode 100644 (file)
index 0000000..2bd5503
--- /dev/null
@@ -0,0 +1,48 @@
+struct A {
+  public:
+    int x;
+};
+
+struct B : A {
+  float y;
+  float foo();
+};
+
+struct C {
+  C(int i = 10);
+  C(const C&);
+  C &operator=(C&);
+  ~C();
+};
+
+enum E {
+  b = 1
+};
+
+//Friend import tests
+void f();
+int g(int a);
+struct X;
+struct Y;
+
+struct F1 {
+public:
+  int x;
+  friend struct X;
+  friend int g(int);
+  friend void f();
+};
+
+struct F2 {
+public:
+  int x;
+  friend struct X;
+  friend void f();
+};
+
+struct F3 {
+public:
+  int x;
+  friend int g(int);
+  friend void f();
+};
diff --git a/clang/test/ASTMerge/class/Inputs/class2.cpp b/clang/test/ASTMerge/class/Inputs/class2.cpp
new file mode 100644 (file)
index 0000000..6fe38b9
--- /dev/null
@@ -0,0 +1,40 @@
+struct A {
+  public:
+    int x;
+};
+
+struct B : A {
+  int y;
+  int foo();
+};
+
+enum E {
+  a = 0,
+  b = 1
+};
+
+//Friend import tests
+void f();
+int g(int a);
+struct X;
+struct Y;
+
+struct F1 {
+public:
+  int x;
+  friend struct X;
+  friend int g(int);
+  friend void f();
+};
+
+struct F2 {
+public:
+  int x;
+  friend struct X;
+};
+
+struct F3 {
+public:
+  int x;
+  friend void f();
+};
diff --git a/clang/test/ASTMerge/class/test.cpp b/clang/test/ASTMerge/class/test.cpp
new file mode 100644 (file)
index 0000000..ba553af
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/class1.cpp
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/class2.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 -Wno-odr -Werror
+
+// CHECK: class1.cpp:6:8: warning: type 'B' has incompatible definitions in different translation units
+// CHECK: class1.cpp:7:9: note: field 'y' has type 'float' here
+// CHECK: class2.cpp:7:7: note: field 'y' has type 'int' here
+
+// FIXME: we should also complain about mismatched types on the method
+
+// CHECK: class1.cpp:18:6: warning: type 'E' has incompatible definitions in different translation units
+// CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here
+// CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here
+
+// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units
+// CHECK: class1.cpp:46:3: note: friend declared here
+// CHECK: class2.cpp:36:8: note: no corresponding friend here
+
+// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units
+// CHECK: class1.cpp:39:3: note: friend declared here
+// CHECK: class2.cpp:30:8: note: no corresponding friend here
+
+// CHECK: 4 warnings generated.
diff --git a/clang/test/ASTMerge/class2/Inputs/class3.cpp b/clang/test/ASTMerge/class2/Inputs/class3.cpp
new file mode 100644 (file)
index 0000000..428acc3
--- /dev/null
@@ -0,0 +1,26 @@
+class C1 {
+public:
+  C1();
+  ~C1();
+  C1 *method_1() {
+    return this;
+  }
+  C1 method_2() {
+    return C1();
+  }
+  void method_3() {
+    const C1 &ref = C1();
+  }
+};
+
+class C11 : public C1 {
+};
+
+class C2 {
+private:
+  int x;
+  friend class C3;
+public:
+  static_assert(sizeof(x) == sizeof(int), "Error");
+  typedef class C2::C2 InjType;
+};
diff --git a/clang/test/ASTMerge/class2/test.cpp b/clang/test/ASTMerge/class2/test.cpp
new file mode 100644 (file)
index 0000000..6021403
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class C3 {
+  int method_1(C2 *x) {
+    return x->x;
+  }
+};
diff --git a/clang/test/ASTMerge/codegen-body/Inputs/body1.c b/clang/test/ASTMerge/codegen-body/Inputs/body1.c
new file mode 100644 (file)
index 0000000..d4d1e4b
--- /dev/null
@@ -0,0 +1,6 @@
+int f();
+
+int main()
+{
+  return f();
+}
diff --git a/clang/test/ASTMerge/codegen-body/Inputs/body2.c b/clang/test/ASTMerge/codegen-body/Inputs/body2.c
new file mode 100644 (file)
index 0000000..73cb1ed
--- /dev/null
@@ -0,0 +1,4 @@
+__inline__ __attribute__ ((always_inline)) int f()
+{
+  return 2;
+}
diff --git a/clang/test/ASTMerge/codegen-body/test.c b/clang/test/ASTMerge/codegen-body/test.c
new file mode 100644 (file)
index 0000000..7232bf4
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/body1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/body2.c
+// RUN: %clang_cc1 -emit-obj -o /dev/null -ast-merge %t.1.ast -ast-merge %t.2.ast %s
+// expected-no-diagnostics
+
diff --git a/clang/test/ASTMerge/codegen-exprs/Inputs/exprs1.c b/clang/test/ASTMerge/codegen-exprs/Inputs/exprs1.c
new file mode 100644 (file)
index 0000000..1c268da
--- /dev/null
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+  E0_Val0 = 'a',
+  E0_Val1 = (17),
+  E0_Val2 = (1 << 2),
+  E0_Val3 = E0_Val2,
+  E0_Val4 = sizeof(int*),
+  E0_Val5 = (unsigned int)-1
+};
+
diff --git a/clang/test/ASTMerge/codegen-exprs/Inputs/exprs2.c b/clang/test/ASTMerge/codegen-exprs/Inputs/exprs2.c
new file mode 100644 (file)
index 0000000..1c268da
--- /dev/null
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+  E0_Val0 = 'a',
+  E0_Val1 = (17),
+  E0_Val2 = (1 << 2),
+  E0_Val3 = E0_Val2,
+  E0_Val4 = sizeof(int*),
+  E0_Val5 = (unsigned int)-1
+};
+
diff --git a/clang/test/ASTMerge/codegen-exprs/test.c b/clang/test/ASTMerge/codegen-exprs/test.c
new file mode 100644 (file)
index 0000000..b5069f9
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-pch -o %t.1.ast %S/Inputs/exprs1.c
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-pch -o %t.2.ast %S/Inputs/exprs2.c
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-obj -o /dev/null -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
diff --git a/clang/test/ASTMerge/enum/Inputs/enum1.c b/clang/test/ASTMerge/enum/Inputs/enum1.c
new file mode 100644 (file)
index 0000000..f2b9c5c
--- /dev/null
@@ -0,0 +1,42 @@
+// Matching
+enum E1 {
+  E1Enumerator1,
+  E1Enumerator2 = 3,
+  E1Enumerator3
+} x1;
+
+// Value mismatch
+enum E2 {
+  E2Enumerator1,
+  E2Enumerator2 = 3,
+  E2Enumerator3
+} x2;
+
+// Name mismatch
+enum E3 {
+  E3Enumerator1,
+  E3Enumerator2 = 3,
+  E3Enumerator3
+} x3;
+
+// Missing enumerator
+enum E4 {
+  E4Enumerator1,
+  E4Enumerator2,
+  E4Enumerator3
+} x4;
+
+// Extra enumerator
+enum E5 {
+  E5Enumerator1,
+  E5Enumerator2,
+  E5Enumerator3
+} x5;
+
+// Matching, with typedef
+typedef enum {
+  E6Enumerator1,
+  E6Enumerator2
+} E6;
+
+E6 x6;
diff --git a/clang/test/ASTMerge/enum/Inputs/enum2.c b/clang/test/ASTMerge/enum/Inputs/enum2.c
new file mode 100644 (file)
index 0000000..315b4dc
--- /dev/null
@@ -0,0 +1,42 @@
+// Matching
+enum E1 {
+  E1Enumerator1,
+  E1Enumerator2 = 3,
+  E1Enumerator3
+} x1;
+
+// Value mismatch
+enum E2 {
+  E2Enumerator1,
+  E2Enumerator2 = 4,
+  E2Enumerator3
+} x2;
+
+// Name mismatch
+enum E3 {
+  E3Enumerator1,
+  E3Enumerator = 3,
+  E3Enumerator3
+} x3;
+
+// Missing enumerator
+enum E4 {
+  E4Enumerator1,
+  E4Enumerator2
+} x4;
+
+// Extra enumerator
+enum E5 {
+  E5Enumerator1,
+  E5Enumerator2,
+  E5Enumerator3,
+  E5Enumerator4
+} x5;
+
+// Matching, with typedef
+typedef enum {
+  E6Enumerator1,
+  E6Enumerator2
+} E6;
+
+E6 x6;
diff --git a/clang/test/ASTMerge/enum/test.c b/clang/test/ASTMerge/enum/test.c
new file mode 100644 (file)
index 0000000..57f9278
--- /dev/null
@@ -0,0 +1,27 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/enum1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/enum2.c
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: enum1.c:9:6: warning: type 'enum E2' has incompatible definitions in different translation units
+// CHECK: enum1.c:11:3: note: enumerator 'E2Enumerator2' with value 3 here
+// CHECK: enum2.c:11:3: note: enumerator 'E2Enumerator2' with value 4 here
+// CHECK: enum2.c:13:3: error: external variable 'x2' declared with incompatible types in different translation units ('enum E2' vs. 'enum E2')
+// CHECK: enum1.c:13:3: note: declared here with type 'enum E2'
+// CHECK: enum1.c:16:6: warning: type 'enum E3' has incompatible definitions in different translation units
+// CHECK: enum1.c:18:3: note: enumerator 'E3Enumerator2' with value 3 here
+// CHECK: enum2.c:18:3: note: enumerator 'E3Enumerator' with value 3 here
+// CHECK: enum2.c:20:3: error: external variable 'x3' declared with incompatible types in different translation units ('enum E3' vs. 'enum E3')
+// CHECK: enum1.c:20:3: note: declared here with type 'enum E3'
+// CHECK: enum1.c:23:6: warning: type 'enum E4' has incompatible definitions in different translation units
+// CHECK: enum1.c:26:3: note: enumerator 'E4Enumerator3' with value 2 here
+// CHECK: enum2.c:23:6: note: no corresponding enumerator here
+// CHECK: enum2.c:26:3: error: external variable 'x4' declared with incompatible types in different translation units ('enum E4' vs. 'enum E4')
+// CHECK: enum1.c:27:3: note: declared here with type 'enum E4'
+// CHECK: enum1.c:30:6: warning: type 'enum E5' has incompatible definitions in different translation units
+// CHECK: enum2.c:33:3: note: enumerator 'E5Enumerator4' with value 3 here
+// CHECK: enum1.c:30:6: note: no corresponding enumerator here
+// CHECK: enum2.c:34:3: error: external variable 'x5' declared with incompatible types in different translation units ('enum E5' vs. 'enum E5')
+// CHECK: enum1.c:34:3: note: declared here with type 'enum E5'
+// CHECK: 4 warnings and 4 errors generated
diff --git a/clang/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp b/clang/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
new file mode 100644 (file)
index 0000000..6fdc33f
--- /dev/null
@@ -0,0 +1,141 @@
+// Integer literals
+const char Ch1 = 'a';
+const signed char Ch2 = 'b';
+const unsigned char Ch3 = 'c';
+
+const wchar_t Ch4 = L'd';
+const signed wchar_t Ch5 = L'e';
+const unsigned wchar_t Ch6 = L'f';
+
+const short C1 = 12;
+const unsigned short C2 = 13;
+
+const int C3 = 12;
+const unsigned int C4 = 13;
+
+const long C5 = 22;
+const unsigned long C6 = 23;
+
+const long long C7 = 66;
+const unsigned long long C8 = 67;
+
+
+// String literals
+const char str1[] = "ABCD";
+const char str2[] = "ABCD" "0123";
+
+const wchar_t wstr1[] = L"DEF";
+const wchar_t wstr2[] = L"DEF" L"123";
+
+
+// Boolean literals
+const bool bval1 = true;
+const bool bval2 = false;
+
+// Floating Literals
+const float F1 = 12.2F;
+const double F2 = 1E4;
+const long double F3 = 1.2E-3L;
+
+
+// nullptr literal
+const void *vptr = nullptr;
+
+
+int glb_1[4] = { 10, 20, 30, 40 };
+
+struct S1 {
+  int a;
+  int b[3];
+};
+
+struct S2 {
+  int c;
+  S1 d;
+};
+
+S2 glb_2 = { 22, .d.a = 44, .d.b[0] = 55, .d.b[1] = 66 };
+
+void testNewThrowDelete() {
+  throw;
+  char *p = new char[10];
+  delete[] p;
+}
+
+int testArrayElement(int *x, int n) {
+  return x[n];
+}
+
+int testTernaryOp(int c, int x, int y) {
+  return c ? x : y;
+}
+
+S1 &testConstCast(const S1 &x) {
+  return const_cast<S1&>(x);
+}
+
+S1 &testStaticCast(S1 &x) {
+  return static_cast<S1&>(x);
+}
+
+S1 &testReinterpretCast(S1 &x) {
+  return reinterpret_cast<S1&>(x);
+}
+
+S1 &testDynamicCast(S1 &x) {
+  return dynamic_cast<S1&>(x);
+}
+
+int testScalarInit(int x) {
+  return int(x);
+}
+
+struct S {
+  float f;
+  double d;
+};
+struct T {
+  int i;
+  struct S s[10];
+};
+
+void testOffsetOf() {
+  __builtin_offsetof(struct T, s[2].d);
+}
+
+
+int testDefaultArg(int a = 2*2) {
+  return a;
+}
+
+int testDefaultArgExpr() {
+  return testDefaultArg();
+}
+
+template <typename T> // T has TemplateTypeParmType
+void testTemplateTypeParmType(int i);
+
+void useTemplateType() {
+  testTemplateTypeParmType<char>(4);
+}
+
+const bool ExpressionTrait = __is_lvalue_expr(1);
+const unsigned ArrayRank = __array_rank(int[10][20]);
+const unsigned ArrayExtent = __array_extent(int[10][20], 1);
+
+constexpr int testLambdaAdd(int toAdd) {
+  const int Captured1 = 1, Captured2 = 2;
+  constexpr auto LambdaAdd = [Captured1, Captured2](int k) -> int {
+    return Captured1 + Captured2 + k;
+  };
+  return LambdaAdd(toAdd);
+}
+
+template<typename T>
+struct TestLambdaTemplate {
+  T i, j;
+  TestLambdaTemplate(T i, const T &j) : i(i), j(j) {}
+  T testLambda(T k) {
+    return [this](T k) -> decltype(auto) { return i + j + k; }(k);
+  }
+};
diff --git a/clang/test/ASTMerge/exprs-cpp/test.cpp b/clang/test/ASTMerge/exprs-cpp/test.cpp
new file mode 100644 (file)
index 0000000..c0b282e
--- /dev/null
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/exprs3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(Ch1 == 'a');
+static_assert(Ch2 == 'b');
+static_assert(Ch3 == 'c');
+
+static_assert(Ch4 == L'd');
+static_assert(Ch5 == L'e');
+static_assert(Ch6 == L'f');
+
+static_assert(C1 == 12);
+static_assert(C2 == 13);
+
+static_assert(C3 == 12);
+static_assert(C4 == 13);
+
+static_assert(C5 == 22L);
+static_assert(C6 == 23L);
+
+static_assert(C7 == 66LL);
+static_assert(C8 == 67ULL);
+
+static_assert(bval1 == true);
+static_assert(bval2 == false);
+
+static_assert(ExpressionTrait == false);
+
+static_assert(ArrayRank == 2);
+static_assert(ArrayExtent == 20);
+
+static_assert(testLambdaAdd(3) == 6);
+
+void testImport(int *x, const S1 &cs1, S1 &s1) {
+  testNewThrowDelete();
+  testArrayElement(nullptr, 12);
+  testTernaryOp(0, 1, 2);
+  testConstCast(cs1);
+  testStaticCast(s1);
+  testReinterpretCast(s1);
+  testDynamicCast(s1);
+  testScalarInit(42);
+  testOffsetOf();
+  testDefaultArg(12);
+  testDefaultArg();
+  testDefaultArgExpr();
+  useTemplateType();
+  TestLambdaTemplate<int>(1, 2).testLambda(3);
+}
diff --git a/clang/test/ASTMerge/exprs/Inputs/exprs1.c b/clang/test/ASTMerge/exprs/Inputs/exprs1.c
new file mode 100644 (file)
index 0000000..1c268da
--- /dev/null
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+  E0_Val0 = 'a',
+  E0_Val1 = (17),
+  E0_Val2 = (1 << 2),
+  E0_Val3 = E0_Val2,
+  E0_Val4 = sizeof(int*),
+  E0_Val5 = (unsigned int)-1
+};
+
diff --git a/clang/test/ASTMerge/exprs/Inputs/exprs2.c b/clang/test/ASTMerge/exprs/Inputs/exprs2.c
new file mode 100644 (file)
index 0000000..1c268da
--- /dev/null
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+  E0_Val0 = 'a',
+  E0_Val1 = (17),
+  E0_Val2 = (1 << 2),
+  E0_Val3 = E0_Val2,
+  E0_Val4 = sizeof(int*),
+  E0_Val5 = (unsigned int)-1
+};
+
diff --git a/clang/test/ASTMerge/exprs/test.c b/clang/test/ASTMerge/exprs/test.c
new file mode 100644 (file)
index 0000000..7495bb6
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-pch -o %t.1.ast %S/Inputs/exprs1.c
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-pch -o %t.2.ast %S/Inputs/exprs2.c
+// RUN: %clang_cc1 -triple %itanium_abi_triple -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
diff --git a/clang/test/ASTMerge/function-cpp/Inputs/function-1.cpp b/clang/test/ASTMerge/function-cpp/Inputs/function-1.cpp
new file mode 100644 (file)
index 0000000..ee97a1a
--- /dev/null
@@ -0,0 +1,8 @@
+
+template<typename T> constexpr T add(T arg1, T arg2) {
+  return arg1 + arg2;
+}
+
+template<> constexpr int add(int arg1, int arg2) {
+  return arg1 + arg2 + 2;
+}
diff --git a/clang/test/ASTMerge/function-cpp/test.cpp b/clang/test/ASTMerge/function-cpp/test.cpp
new file mode 100644 (file)
index 0000000..304ce3c
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/function-1.cpp
+// RUN: %clang_cc1 -std=c++1z  -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck %s
+// XFAIL: *
+
+static_assert(add(1, 2) == 5);
+
+// FIXME: support of templated function overload is still not implemented.
+static_assert(add('\1', '\2') == 3);
+
+// CHECK-NOT: static_assert
diff --git a/clang/test/ASTMerge/function/Inputs/function1.c b/clang/test/ASTMerge/function/Inputs/function1.c
new file mode 100644 (file)
index 0000000..4523bd3
--- /dev/null
@@ -0,0 +1,6 @@
+void f0(int);
+void f1(int, float);
+void f2();
+void f3(void);
+void f4(int, int);
+int f5(int) __attribute__((const));
diff --git a/clang/test/ASTMerge/function/Inputs/function2.c b/clang/test/ASTMerge/function/Inputs/function2.c
new file mode 100644 (file)
index 0000000..6ca810a
--- /dev/null
@@ -0,0 +1,7 @@
+typedef int Int;
+void f0(Int);
+void f1(Int, double);
+void f2(int, int);
+void f3(int);
+static void f4(float, float);
+int f5(int) __attribute__((const));
diff --git a/clang/test/ASTMerge/function/test.c b/clang/test/ASTMerge/function/test.c
new file mode 100644 (file)
index 0000000..8d4d0c1
--- /dev/null
@@ -0,0 +1,17 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/function1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/function2.c
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
+
+// CHECK: function2.c:3:6: error: external function 'f1' declared with incompatible types in different translation units ('void (Int, double)' (aka 'void (int, double)') vs. 'void (int, float)')
+// CHECK: function1.c:2:6: note: declared here with type 'void (int, float)'
+// CHECK: function2.c:5:6: error: external function 'f3' declared with incompatible types in different translation units ('void (int)' vs. 'void (void)')
+// CHECK: function1.c:4:6: note: declared here with type 'void (void)'
+// CHECK: 2 errors generated
+
+// expected-error@Inputs/function2.c:3 {{external function 'f1' declared with incompatible types}}
+// expected-note@Inputs/function1.c:2 {{declared here}}
+// expected-error@Inputs/function2.c:5 {{external function 'f3' declared with incompatible types}}
+// expected-note@Inputs/function1.c:4 {{declared here}}
diff --git a/clang/test/ASTMerge/inheritance/Inputs/inheritance-base.cpp b/clang/test/ASTMerge/inheritance/Inputs/inheritance-base.cpp
new file mode 100644 (file)
index 0000000..26fe42e
--- /dev/null
@@ -0,0 +1,7 @@
+class A
+{
+public:
+  int x;
+  A(int _x) : x(_x) {
+  }
+};
diff --git a/clang/test/ASTMerge/inheritance/test.cpp b/clang/test/ASTMerge/inheritance/test.cpp
new file mode 100644 (file)
index 0000000..7fce82a
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/inheritance-base.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class B : public A {
+  B(int _a) : A(_a) {
+  }
+};
diff --git a/clang/test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp b/clang/test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp
new file mode 100644 (file)
index 0000000..fd51f86
--- /dev/null
@@ -0,0 +1,19 @@
+class A_base
+{
+public:
+  int x;
+  A_base() : x(0) {
+  }
+  A_base(int _x) : x(static_cast<int>(_x)) {
+  }
+};
+
+class A : public A_base
+{
+public:
+  int y;
+  struct { int z; };
+  int array[2];
+  A(int _x) : A_base(_x), y(0), z(1), array{{2},{3}} {
+  }
+};
diff --git a/clang/test/ASTMerge/init-ctors/test.cpp b/clang/test/ASTMerge/init-ctors/test.cpp
new file mode 100644 (file)
index 0000000..5f0ba4d
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/init-ctors-classes.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class B {
+  int method_1() {
+    A a(0);
+    return a.x;
+  }
+};
diff --git a/clang/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp b/clang/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
new file mode 100644 (file)
index 0000000..f6f7697
--- /dev/null
@@ -0,0 +1,2 @@
+template <class X>
+class C { static X x; };
diff --git a/clang/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp b/clang/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
new file mode 100644 (file)
index 0000000..7cf5fc2
--- /dev/null
@@ -0,0 +1,2 @@
+template <class X>
+X C<X>::x;
diff --git a/clang/test/ASTMerge/injected-class-name-decl/test.cpp b/clang/test/ASTMerge/injected-class-name-decl/test.cpp
new file mode 100644 (file)
index 0000000..9f31674
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.ast %S/Inputs/inject1.cpp
+// RUN: %clang_cc1 -std=c++1z -emit-obj -o /dev/null -ast-merge %t.ast %S/Inputs/inject2.cpp
+// expected-no-diagnostics
diff --git a/clang/test/ASTMerge/interface/Inputs/interface1.m b/clang/test/ASTMerge/interface/Inputs/interface1.m
new file mode 100644 (file)
index 0000000..6192150
--- /dev/null
@@ -0,0 +1,105 @@
+// Matches
+@interface I1 {
+  int ivar1;
+}
+@end
+
+// Matches
+@interface I2 : I1 {
+  float ivar2;
+}
+@end
+
+// Ivar mismatch
+@interface I3 {
+  int ivar1;
+  int ivar2;
+}
+@end
+
+// Superclass mismatch
+@interface I4 : I2 {
+}
+@end
+
+// Methods match
+@interface I5
+- (int)foo;
++ (float)bar;
+@end
+
+// Method mismatch
+@interface I6
+- (int)foo;
++ (int)foo;
+@end
+
+// Method mismatch
+@interface I7
+- (int)foo;
++ (int)bar:(int)x;
+@end
+
+// Method mismatch
+@interface I8
+- (int)foo;
++ (int)bar:(float)x;
+@end
+
+// Matching protocol
+@protocol P0
++ (int)foo;
+- (int)bar:(float)x;
+@end
+
+// Protocol with mismatching method
+@protocol P1
++ (int)foo;
+- (int)bar:(float)x;
+@end
+
+// Interface with protocol
+@interface I9 <P0>
++ (int)foo;
+- (int)bar:(float)x;
+@end
+
+// Protocol with protocol
+@protocol P2 <P0>
+- (float)wibble:(int)a1 second:(int)a2;
+@end
+
+// Forward-declared interfaces
+@class I10, I11;
+@interface I12
+@end
+
+// Forward-declared protocols
+@protocol P3, P5;
+@protocol P4
+- (double)honk:(int)a;
+@end
+
+// Interface with implementation
+@interface I13
+@end
+
+@implementation I13
+@end
+
+@interface I13a
+@end
+
+@implementation I13a
+@end
+
+// Implementation by itself
+@implementation I14 : I12
+@end
+
+@implementation I15 : I12
+@end
+
+@interface ImportSelectorSLoc { }
+-(int)addInt:(int)a toInt:(int)b moduloInt:(int)c; // don't crash here
+@end
diff --git a/clang/test/ASTMerge/interface/Inputs/interface2.m b/clang/test/ASTMerge/interface/Inputs/interface2.m
new file mode 100644 (file)
index 0000000..2133bd1
--- /dev/null
@@ -0,0 +1,100 @@
+// Matches
+@interface I1 {
+  int ivar1;
+}
+@end
+
+// Matches
+@interface I2 : I1 {
+  float ivar2;
+}
+@end
+
+// Ivar mismatch
+@interface I3 {
+  int ivar1;
+  float ivar2;
+}
+@end
+
+// Superclass mismatch
+@interface I4 : I1 {
+}
+@end
+
+// Methods match
+@interface I5
++ (float)bar;
+- (int)foo;
+@end
+
+// Method mismatch
+@interface I6
++ (float)foo;
+@end
+
+// Method mismatch
+@interface I7
+- (int)foo;
++ (int)bar:(float)x;
+@end
+
+// Method mismatch
+@interface I8
+- (int)foo;
++ (int)bar:(float)x, ...;
+@end
+
+// Matching protocol
+@protocol P0
++ (int)foo;
+- (int)bar:(float)x;
+@end
+
+// Protocol with mismatching method
+@protocol P1
++ (int)foo;
+- (int)bar:(double)x;
+@end
+
+// Interface with protocol
+@interface I9 <P0>
++ (int)foo;
+- (int)bar:(float)x;
+@end
+
+// Protocol with protocol
+@protocol P2 <P0>
+- (float)wibble:(int)a1 second:(int)a2;
+@end
+
+// Forward-declared interface
+@class I10; @interface I12 @end
+@interface I11
+@end
+
+// Forward-declared protocols
+@protocol P3, P4;
+@protocol P5
+- (double)honk:(int)a;
+@end
+
+// Interface with implementation
+@interface I13
+@end
+
+@implementation I13
+@end
+
+@interface I13b
+@end
+
+@implementation I13b
+@end
+
+// Implementation by itself
+@implementation I14 : I12
+@end
+
+@implementation I15 : I11
+@end
diff --git a/clang/test/ASTMerge/interface/test.m b/clang/test/ASTMerge/interface/test.m
new file mode 100644 (file)
index 0000000..7338e90
--- /dev/null
@@ -0,0 +1,24 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/interface1.m
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/interface2.m
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: interface2.m:16:9: error: instance variable 'ivar2' declared with incompatible types in different translation units ('float' vs. 'int')
+// CHECK: interface1.m:16:7: note: declared here with type 'int'
+// CHECK: interface1.m:21:12: error: class 'I4' has incompatible superclasses
+// CHECK: interface1.m:21:17: note: inherits from superclass 'I2' here
+// CHECK: interface2.m:21:17: note: inherits from superclass 'I1' here
+// CHECK: interface2.m:33:1: error: class method 'foo' has incompatible result types in different translation units ('float' vs. 'int')
+// CHECK: interface1.m:34:1: note: class method 'foo' also declared here
+// CHECK: interface2.m:39:19: error: class method 'bar:' has a parameter with a different types in different translation units ('float' vs. 'int')
+// CHECK: interface1.m:40:17: note: declared here with type 'int'
+// CHECK: interface2.m:45:1: error: class method 'bar:' is variadic in one translation unit and not variadic in another
+// CHECK: interface1.m:46:1: note: class method 'bar:' also declared here
+// CHECK: interface2.m:57:20: error: instance method 'bar:' has a parameter with a different types in different translation units ('double' vs. 'float')
+// CHECK: interface1.m:58:19: note: declared here with type 'float'
+// CHECK: interface1.m:100:17: error: class 'I15' has incompatible superclasses
+// CHECK: interface1.m:100:17: note: inherits from superclass 'I12' here
+// CHECK: interface2.m:99:17: note: inherits from superclass 'I11' here
+// CHECK: 8 errors generated
+
diff --git a/clang/test/ASTMerge/macro/Inputs/macro.modulemap b/clang/test/ASTMerge/macro/Inputs/macro.modulemap
new file mode 100644 (file)
index 0000000..dba1f22
--- /dev/null
@@ -0,0 +1,4 @@
+module macro1 [extern_c] {
+  header "macro1.h"
+  export *
+}
diff --git a/clang/test/ASTMerge/macro/Inputs/macro1.h b/clang/test/ASTMerge/macro/Inputs/macro1.h
new file mode 100644 (file)
index 0000000..9613394
--- /dev/null
@@ -0,0 +1,5 @@
+typedef void *VoidRef;
+
+void maybeNull(
+  int i,
+  _Nullable VoidRef *_Nullable);
diff --git a/clang/test/ASTMerge/macro/Inputs/macro1.m b/clang/test/ASTMerge/macro/Inputs/macro1.m
new file mode 100644 (file)
index 0000000..2612613
--- /dev/null
@@ -0,0 +1,5 @@
+@import macro1;
+
+void foo() {
+  maybeNull(0, 0);
+}
diff --git a/clang/test/ASTMerge/macro/Inputs/macro2.m b/clang/test/ASTMerge/macro/Inputs/macro2.m
new file mode 100644 (file)
index 0000000..b5b155a
--- /dev/null
@@ -0,0 +1,5 @@
+void foo();
+
+void bar() {
+  foo();
+}
diff --git a/clang/test/ASTMerge/macro/test.m b/clang/test/ASTMerge/macro/test.m
new file mode 100644 (file)
index 0000000..77e596d
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/cache
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fmodule-map-file=%S/Inputs/macro.modulemap -I%S/Inputs -emit-pch -o %t.1.ast %S/Inputs/macro1.m
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fmodule-map-file=%S/Inputs/macro.modulemap -I%S/Inputs -emit-pch -o %t.2.ast %S/Inputs/macro2.m
+// RUN: %clang_cc1 -fmodules -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
diff --git a/clang/test/ASTMerge/namespace/Inputs/namespace1.cpp b/clang/test/ASTMerge/namespace/Inputs/namespace1.cpp
new file mode 100644 (file)
index 0000000..4a53952
--- /dev/null
@@ -0,0 +1,27 @@
+// Merge success
+namespace N1 {
+  int x;
+}
+
+// Merge multiple namespaces
+namespace N2 {
+  extern int x;
+}
+namespace N2 {
+  extern float y;
+}
+
+// Merge namespace with conflict
+namespace N3 {
+  extern float z;
+}
+
+namespace AliasWithSameName = N3;
+
+namespace TestUnresolvedTypenameAndValueDecls {
+template <class T> class Base {
+public:
+  typedef T foo;
+  void bar();
+};
+}
diff --git a/clang/test/ASTMerge/namespace/Inputs/namespace2.cpp b/clang/test/ASTMerge/namespace/Inputs/namespace2.cpp
new file mode 100644 (file)
index 0000000..f65057d
--- /dev/null
@@ -0,0 +1,60 @@
+// Merge success
+namespace N1 {
+  extern int x0;
+}
+
+// Merge multiple namespaces
+namespace N2 {
+  extern int x;
+}
+namespace N2 {
+  extern float y;
+}
+
+// Merge namespace with conflict
+namespace N3 {
+  extern double z;
+}
+
+namespace Enclosing {
+namespace Nested {
+  const int z = 4;
+}
+}
+
+namespace ContainsInline {
+  inline namespace Inline {
+    const int z = 10;
+  }
+}
+
+namespace TestAliasName = Enclosing::Nested;
+// NOTE: There is no warning on this alias.
+namespace AliasWithSameName = Enclosing::Nested;
+
+namespace TestUsingDecls {
+
+namespace A {
+void foo();
+}
+namespace B {
+using A::foo; // <- a UsingDecl creating a UsingShadow
+}
+
+}// end namespace TestUsingDecls
+
+namespace TestUnresolvedTypenameAndValueDecls {
+
+template <class T> class Base;
+template <class T> class Derived : public Base<T> {
+public:
+  using typename Base<T>::foo;
+  using Base<T>::bar;
+  typedef typename Derived::foo NewUnresolvedUsingType;
+};
+
+} // end namespace TestUnresolvedTypenameAndValueDecls
+
+namespace TestUsingNamespace {
+  using namespace Enclosing;
+}
diff --git a/clang/test/ASTMerge/namespace/test.cpp b/clang/test/ASTMerge/namespace/test.cpp
new file mode 100644 (file)
index 0000000..f0f8b73
--- /dev/null
@@ -0,0 +1,19 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.1.ast %S/Inputs/namespace1.cpp
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.2.ast %S/Inputs/namespace2.cpp
+// RUN: not %clang_cc1 -std=c++1z -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+static_assert(TestAliasName::z == 4);
+static_assert(ContainsInline::z == 10);
+
+void testImport() {
+  typedef TestUnresolvedTypenameAndValueDecls::Derived<int> Imported;
+  Imported a; // Successful instantiation
+  static_assert(sizeof(Imported::foo) == sizeof(int));
+  static_assert(sizeof(TestUnresolvedTypenameAndValueDecls::Derived<double>::NewUnresolvedUsingType) == sizeof(double));
+}
+
+
+// CHECK: namespace2.cpp:16:17: error: external variable 'z' declared with incompatible types in different translation units ('double' vs. 'float')
+// CHECK: namespace1.cpp:16:16: note: declared here with type 'float'
diff --git a/clang/test/ASTMerge/property/Inputs/property1.m b/clang/test/ASTMerge/property/Inputs/property1.m
new file mode 100644 (file)
index 0000000..22fe0a0
--- /dev/null
@@ -0,0 +1,31 @@
+// Matching properties
+@interface I1 {
+}
+- (int)getProp2;
+- (void)setProp2:(int)value;
+@end
+
+// Mismatched property
+@interface I2
+@property (readonly) float Prop1;
+@end
+
+// Properties with implementations
+@interface I3 {
+  int ivar1;
+  int ivar2;
+  int ivar3;
+  int Prop4;
+}
+@property int Prop1;
+@property int Prop2;
+@property int Prop3;
+@property int Prop4;
+@end
+
+@implementation I3
+@synthesize Prop1 = ivar1;
+@synthesize Prop2 = ivar3;
+@dynamic Prop3;
+@synthesize Prop4;
+@end
diff --git a/clang/test/ASTMerge/property/Inputs/property2.m b/clang/test/ASTMerge/property/Inputs/property2.m
new file mode 100644 (file)
index 0000000..64a03fb
--- /dev/null
@@ -0,0 +1,33 @@
+// Matching properties
+@interface I1 {
+}
+- (int)getProp2;
+- (void)setProp2:(int)value;
+@property (readonly) int Prop1;
+@property (getter = getProp2, setter = setProp2:) int Prop2;
+@end
+
+// Mismatched property
+@interface I2
+@property (readonly) int Prop1;
+@end
+
+// Properties with implementations
+@interface I3 {
+  int ivar1;
+  int ivar2;
+  int ivar3;
+  int Prop4;
+}
+@property int Prop1;
+@property int Prop2;
+@property int Prop3;
+@property int Prop4;
+@end
+
+@implementation I3
+@synthesize Prop2 = ivar2;
+@synthesize Prop1 = ivar1;
+@synthesize Prop3 = ivar3;
+@synthesize Prop4 = Prop4;
+@end
diff --git a/clang/test/ASTMerge/property/test.m b/clang/test/ASTMerge/property/test.m
new file mode 100644 (file)
index 0000000..e48d54e
--- /dev/null
@@ -0,0 +1,15 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/property1.m
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/property2.m
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: property2.m:12:26: error: property 'Prop1' declared with incompatible types in different translation units ('int' vs. 'float')
+// CHECK: property1.m:10:28: note: declared here with type 'float'
+// CHECK: property2.m:12:26: error: instance method 'Prop1' has incompatible result types in different translation units ('int' vs. 'float')
+// CHECK: property1.m:10:28: note: instance method 'Prop1' also declared here
+// CHECK: property1.m:28:21: error: property 'Prop2' is synthesized to different ivars in different translation units ('ivar3' vs. 'ivar2')
+// CHECK: property2.m:29:21: note: property is synthesized to ivar 'ivar2' here
+// CHECK: property1.m:29:10: error: property 'Prop3' is implemented with @dynamic in one translation but @synthesize in another translation unit
+// CHECK: property2.m:31:13: note: property 'Prop3' is implemented with @synthesize here
+// CHECK: 4 errors generated.
diff --git a/clang/test/ASTMerge/std-initializer-list/Inputs/il.cpp b/clang/test/ASTMerge/std-initializer-list/Inputs/il.cpp
new file mode 100644 (file)
index 0000000..3b2ac18
--- /dev/null
@@ -0,0 +1,9 @@
+namespace std {
+template <typename T>
+struct initializer_list {
+  const T *begin, *end;
+  initializer_list();
+};
+} // namespace std
+
+std::initializer_list<int> IL = {1, 2, 3, 4};
diff --git a/clang/test/ASTMerge/std-initializer-list/test.cpp b/clang/test/ASTMerge/std-initializer-list/test.cpp
new file mode 100644 (file)
index 0000000..ca7330d
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: unsupported AST node
diff --git a/clang/test/ASTMerge/struct/Inputs/struct1.c b/clang/test/ASTMerge/struct/Inputs/struct1.c
new file mode 100644 (file)
index 0000000..a85aec7
--- /dev/null
@@ -0,0 +1,141 @@
+typedef int Int;
+typedef float Float;
+
+// Matches
+struct S0 {
+  Int field1;
+  Float field2;
+};
+
+struct S0 x0;
+
+// Mismatch in field type
+struct S1 {
+  Int field1;
+  int field2;
+};
+
+struct S1 x1;
+
+// Mismatch in tag kind.
+struct S2 { int i; float f; } x2;
+
+// Missing fields
+struct S3 { int i; float f; double d; } x3;
+
+// Extra fields
+struct S4 { int i; } x4;
+
+// Bit-field matches
+struct S5 { int i : 8; unsigned j : 8; } x5;
+
+// Bit-field mismatch
+struct S6 { int i : 8; unsigned j : 8; } x6;
+
+// Bit-field mismatch
+struct S7 { int i : 8; unsigned j : 8; } x7;
+
+// Incomplete type
+struct S8 *x8;
+
+// Incomplete type
+struct S9 { int i; float f; } *x9;
+
+// Incomplete type
+struct S10 *x10;
+
+// Matches
+struct ListNode {
+  int value;
+  struct ListNode *Next;
+} xList;
+
+// Mismatch due to struct used internally
+struct DeepError {
+  int value;
+  struct DeeperError { int i; int f; } *Deeper;
+} xDeep;
+
+// Matches
+struct {
+  Int i;
+  float f;
+} x11;
+
+// Matches
+typedef struct {
+  Int i;
+  float f;
+} S12;
+
+S12 x12;
+
+// Mismatch
+typedef struct {
+  Float i; // Mismatch here.
+  float f;
+} S13;
+
+S13 x13;
+
+// Matches
+struct Unnamed {
+  union {
+    struct {
+      int i;
+    } S;
+    struct {
+      float i;
+    } R;
+  } U;
+} x14;
+
+// Matches
+struct DeepUnnamed {
+  union {
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        int i;
+      } R;
+    } U1;
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        float i;
+      } T;
+    } U2;
+  } U;
+  struct {
+    long i;
+  } V;
+} x15;
+
+// Mismatch due to unnamed struct used internally
+struct DeepUnnamedError {
+  union {
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        int i;
+      } R;
+    } U1;
+    union {
+      struct {
+        long i; // Mismatch here.
+      } S;
+      struct {
+        float i;
+      } T;
+    } U2;
+  } U;
+  struct {
+    long i;
+  } V;
+} x16;
diff --git a/clang/test/ASTMerge/struct/Inputs/struct2.c b/clang/test/ASTMerge/struct/Inputs/struct2.c
new file mode 100644 (file)
index 0000000..49fe36d
--- /dev/null
@@ -0,0 +1,138 @@
+// Matches
+struct S0 {
+  int field1;
+  float field2;
+};
+
+struct S0 x0;
+
+// Mismatch in field type
+struct S1 {
+  int field1;
+  float field2;
+};
+
+struct S1 x1;
+
+// Mismatch in tag kind.
+union S2 { int i; float f; } x2;
+
+// Missing fields
+struct S3 { int i; float f; } x3;
+
+// Extra fields
+struct S4 { int i; float f; } x4;
+
+// Bit-field matches
+struct S5 { int i : 8; unsigned j : 8; } x5;
+
+// Bit-field mismatch
+struct S6 { int i : 8; unsigned j; } x6;
+
+// Bit-field mismatch
+struct S7 { int i : 8; unsigned j : 16; } x7;
+
+// Incomplete type
+struct S8 { int i; float f; } *x8;
+
+// Incomplete type
+struct S9 *x9;
+
+// Incomplete type
+struct S10 *x10;
+
+// Matches
+struct ListNode {
+  int value;
+  struct ListNode *Next;
+} xList;
+
+// Mismatch due to struct used internally
+struct DeepError {
+  int value;
+  struct DeeperError { int i; float f; } *Deeper;
+} xDeep;
+
+// Matches
+struct {
+  int i;
+  float f;
+} x11;
+
+// Matches
+typedef struct {
+  int i;
+  float f;
+} S12;
+
+S12 x12;
+
+// Mismatch
+typedef struct {
+  int i; // Mismatch here.
+  float f;
+} S13;
+
+S13 x13;
+
+// Matches
+struct Unnamed {
+  union {
+    struct {
+      int i;
+    } S;
+    struct {
+      float i;
+    } R;
+  } U;
+} x14;
+
+// Matches
+struct DeepUnnamed {
+  union {
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        int i;
+      } R;
+    } U1;
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        float i;
+      } T;
+    } U2;
+  } U;
+  struct {
+    long i;
+  } V;
+} x15;
+
+// Mismatch due to unnamed struct used internally
+struct DeepUnnamedError {
+  union {
+    union {
+      struct {
+        long i;
+      } S;
+      struct {
+        int i;
+      } R;
+    } U1;
+    union {
+      struct {
+        float i; // Mismatch here.
+      } S;
+      struct {
+        float i;
+      } T;
+    } U2;
+  } U;
+  struct {
+    long i;
+  } V;
+} x16;
diff --git a/clang/test/ASTMerge/struct/test.c b/clang/test/ASTMerge/struct/test.c
new file mode 100644 (file)
index 0000000..1f5f66d
--- /dev/null
@@ -0,0 +1,57 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/struct1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/struct2.c
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: struct1.c:13:8: warning: type 'struct S1' has incompatible definitions in different translation units
+// CHECK: struct1.c:15:7: note: field 'field2' has type 'int' here
+// CHECK: struct2.c:12:9: note: field 'field2' has type 'float' here
+// CHECK: struct2.c:15:11: error: external variable 'x1' declared with incompatible types in different translation units ('struct S1' vs. 'struct S1')
+// CHECK: struct1.c:18:11: note: declared here with type 'struct S1'
+// CHECK: struct1.c:21:8: warning: type 'struct S2' has incompatible definitions in different translation units
+// CHECK: struct2.c:18:7: note: 'S2' is a union here
+// CHECK: struct2.c:18:30: error: external variable 'x2' declared with incompatible types in different translation units ('union S2' vs. 'struct S2')
+// CHECK: struct1.c:21:31: note: declared here with type 'struct S2'
+// CHECK: struct1.c:24:8: warning: type 'struct S3' has incompatible definitions in different translation units
+// CHECK: struct1.c:24:36: note: field 'd' has type 'double' here
+// CHECK: struct2.c:21:8: note: no corresponding field here
+// CHECK: struct2.c:21:31: error: external variable 'x3' declared with incompatible types in different translation units ('struct S3' vs. 'struct S3')
+// CHECK: struct1.c:24:41: note: declared here with type 'struct S3'
+// CHECK: struct1.c:27:8: warning: type 'struct S4' has incompatible definitions in different translation units
+// CHECK: struct2.c:24:26: note: field 'f' has type 'float' here
+// CHECK: struct1.c:27:8: note: no corresponding field here
+// CHECK: struct2.c:24:31: error: external variable 'x4' declared with incompatible types in different translation units ('struct S4' vs. 'struct S4')
+// CHECK: struct1.c:27:22: note: declared here with type 'struct S4'
+// CHECK: struct1.c:33:8: warning: type 'struct S6' has incompatible definitions in different translation units
+// CHECK: struct1.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
+// CHECK: struct2.c:30:33: note: field 'j' is not a bit-field
+// CHECK: struct2.c:30:38: error: external variable 'x6' declared with incompatible types in different translation units ('struct S6' vs. 'struct S6')
+// CHECK: struct1.c:33:42: note: declared here with type 'struct S6'
+// CHECK: struct1.c:36:8: warning: type 'struct S7' has incompatible definitions in different translation units
+// CHECK: struct1.c:36:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
+// CHECK: struct2.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 16 here
+// CHECK: struct2.c:33:43: error: external variable 'x7' declared with incompatible types in different translation units ('struct S7' vs. 'struct S7')
+// CHECK: struct1.c:36:42: note: declared here with type 'struct S7'
+// CHECK: struct1.c:56:10: warning: type 'struct DeeperError' has incompatible definitions in different translation units
+// CHECK: struct1.c:56:35: note: field 'f' has type 'int' here
+// CHECK: struct2.c:53:37: note: field 'f' has type 'float' here
+// CHECK: struct1.c:54:8: warning: type 'struct DeepError' has incompatible definitions in different translation units
+// CHECK: struct1.c:56:41: note: field 'Deeper' has type 'struct DeeperError *' here
+// CHECK: struct2.c:53:43: note: field 'Deeper' has type 'struct DeeperError *' here
+// CHECK: struct2.c:54:3: error: external variable 'xDeep' declared with incompatible types in different translation units ('struct DeepError' vs. 'struct DeepError')
+// CHECK: struct1.c:57:3: note: declared here with type 'struct DeepError'
+// CHECK: struct1.c:74:9: warning: type 'S13' has incompatible definitions in different translation units
+// CHECK: struct1.c:75:9: note: field 'i' has type 'Float' (aka 'float') here
+// CHECK: struct2.c:72:7: note: field 'i' has type 'int' here
+// CHECK: struct2.c:76:5: error: external variable 'x13' declared with incompatible types in different translation units ('S13' vs. 'S13')
+// CHECK: struct1.c:79:5: note: declared here with type 'S13'
+// CHECK: struct1.c:130:7: warning: type 'struct DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS:.+]]struct1.c:130:7)' has incompatible definitions in different translation units
+// CHECK: struct1.c:131:14: note: field 'i' has type 'long' here
+// CHECK: struct2.c:128:15: note: field 'i' has type 'float' here
+// CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS]]struct1.c:129:5)' has incompatible definitions in different translation units
+// CHECK: struct1.c:132:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]struct1.c:130:7)' here
+// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
+// CHECK: struct2.c:138:3: error: external variable 'x16' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError')
+// CHECK: struct1.c:141:3: note: declared here with type 'struct DeepUnnamedError'
+// CHECK: 11 warnings and 9 errors generated
diff --git a/clang/test/ASTMerge/typedef/Inputs/typedef1.c b/clang/test/ASTMerge/typedef/Inputs/typedef1.c
new file mode 100644 (file)
index 0000000..5657675
--- /dev/null
@@ -0,0 +1,4 @@
+typedef int Typedef1;
+typedef int Typedef2;
+Typedef1 x1;
+Typedef2 x2;
diff --git a/clang/test/ASTMerge/typedef/Inputs/typedef2.c b/clang/test/ASTMerge/typedef/Inputs/typedef2.c
new file mode 100644 (file)
index 0000000..129d710
--- /dev/null
@@ -0,0 +1,4 @@
+typedef int Typedef1;
+typedef double Typedef2;
+Typedef1 x1;
+Typedef2 x2;
diff --git a/clang/test/ASTMerge/typedef/test.c b/clang/test/ASTMerge/typedef/test.c
new file mode 100644 (file)
index 0000000..ec8355d
--- /dev/null
@@ -0,0 +1,9 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/typedef1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/typedef2.c
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: typedef2.c:4:10: error: external variable 'x2' declared with incompatible types in different translation units ('Typedef2' (aka 'double') vs. 'Typedef2' (aka 'int'))
+// CHECK: typedef1.c:4:10: note: declared here with type 'Typedef2' (aka 'int')
+// CHECK: 1 error
diff --git a/clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp b/clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp
new file mode 100644 (file)
index 0000000..1bb0f35
--- /dev/null
@@ -0,0 +1,3 @@
+void f(int X, int Y, bool Z) {
+  auto x = [X, Y, Z] { (void)Z; };
+}
diff --git a/clang/test/ASTMerge/unnamed_fields/test.cpp b/clang/test/ASTMerge/unnamed_fields/test.cpp
new file mode 100644 (file)
index 0000000..6ae3176
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: warning: field '' declared with incompatible types in different translation units ('bool' vs. 'int')
diff --git a/clang/test/ASTMerge/var-cpp/Inputs/var1.cpp b/clang/test/ASTMerge/var-cpp/Inputs/var1.cpp
new file mode 100644 (file)
index 0000000..e29db9d
--- /dev/null
@@ -0,0 +1,17 @@
+
+template <typename T>
+constexpr T my_pi = T(3.1415926535897932385L);  // variable template
+
+template <> constexpr char my_pi<char> = '3';   // variable template specialization
+
+template <typename T>
+struct Wrapper {
+  template <typename U> static constexpr U my_const = U(1);
+   // Variable template partial specialization with member variable.
+  template <typename U> static constexpr U *my_const<const U *> = (U *)(0);
+};
+
+constexpr char a[] = "hello";
+
+template <> template <>
+constexpr const char *Wrapper<float>::my_const<const char *> = a;
diff --git a/clang/test/ASTMerge/var-cpp/test.cpp b/clang/test/ASTMerge/var-cpp/test.cpp
new file mode 100644 (file)
index 0000000..28d38d5
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-pch -std=c++17 -o %t.1.ast %S/Inputs/var1.cpp
+// RUN: %clang_cc1 -std=c++17 -ast-merge %t.1.ast -fsyntax-only %s 2>&1
+
+static_assert(my_pi<double> == (double)3.1415926535897932385L);
+static_assert(my_pi<char> == '3');
+
+static_assert(Wrapper<int>::my_const<float> == 1.f);
+static_assert(Wrapper<char>::my_const<const float *> == nullptr);
+static_assert(Wrapper<float>::my_const<const char *> == a);
diff --git a/clang/test/ASTMerge/var/Inputs/var1.c b/clang/test/ASTMerge/var/Inputs/var1.c
new file mode 100644 (file)
index 0000000..4f5cbe1
--- /dev/null
@@ -0,0 +1,7 @@
+int *x0;
+float **x1;
+#include "var1.h"
+int xarray0[17];
+int xarray1[];
+int xarray2[18];
+int xarray3[18];
diff --git a/clang/test/ASTMerge/var/Inputs/var1.h b/clang/test/ASTMerge/var/Inputs/var1.h
new file mode 100644 (file)
index 0000000..1518e17
--- /dev/null
@@ -0,0 +1 @@
+double x2;
diff --git a/clang/test/ASTMerge/var/Inputs/var2.c b/clang/test/ASTMerge/var/Inputs/var2.c
new file mode 100644 (file)
index 0000000..01986e4
--- /dev/null
@@ -0,0 +1,7 @@
+int *x0;
+double *x1;
+int x2;
+int xarray0[17];
+int xarray1[17];
+int xarray2[];
+int xarray3[17];
diff --git a/clang/test/ASTMerge/var/test.c b/clang/test/ASTMerge/var/test.c
new file mode 100644 (file)
index 0000000..f0a3d92
--- /dev/null
@@ -0,0 +1,14 @@
+// FIXME: Errors are now warnings.
+// XFAIL: *
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/var1.c
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/var2.c
+// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -fdiagnostics-show-note-include-stack %s 2>&1 | FileCheck %s
+
+// CHECK: var2.c:2:9: error: external variable 'x1' declared with incompatible types in different translation units ('double *' vs. 'float **')
+// CHECK: var1.c:2:9: note: declared here with type 'float **'
+// CHECK: var2.c:3:5: error: external variable 'x2' declared with incompatible types in different translation units ('int' vs. 'double')
+// CHECK: In file included from{{.*}}var1.c:3:
+// CHECK: var1.h:1:8: note: declared here with type 'double'
+// CHECK: error: external variable 'xarray3' declared with incompatible types in different translation units ('int [17]' vs. 'int [18]')
+// CHECK: var1.c:7:5: note: declared here with type 'int [18]'
+// CHECK: 3 errors