summaryrefslogtreecommitdiff
path: root/test/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'test/Modules')
-rw-r--r--test/Modules/Inputs/CmdLine.framework/Headers/CmdLine.h6
-rw-r--r--test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h3
-rw-r--r--test/Modules/Inputs/Module.framework/Headers/Module.h12
-rw-r--r--test/Modules/Inputs/MutuallyRecursive1.framework/Headers/MutuallyRecursive1.h3
-rw-r--r--test/Modules/Inputs/MutuallyRecursive2.framework/Headers/MutuallyRecursive2.h6
-rw-r--r--test/Modules/Inputs/diamond_bottom.h4
-rw-r--r--test/Modules/Inputs/diamond_left.h9
-rw-r--r--test/Modules/Inputs/diamond_right.h7
-rw-r--r--test/Modules/Inputs/diamond_top.h4
-rw-r--r--test/Modules/Inputs/load_failure.h1
-rw-r--r--test/Modules/Inputs/lookup_left.h3
-rw-r--r--test/Modules/Inputs/lookup_left.hpp5
-rw-r--r--test/Modules/Inputs/lookup_right.h5
-rw-r--r--test/Modules/Inputs/lookup_right.hpp1
-rw-r--r--test/Modules/Inputs/point.h2
-rw-r--r--test/Modules/auto-module-import.c13
-rw-r--r--test/Modules/cycles.c12
-rw-r--r--test/Modules/diamond.c27
-rw-r--r--test/Modules/driver.c6
-rw-r--r--test/Modules/header-import.m7
-rw-r--r--test/Modules/irgen.c15
-rw-r--r--test/Modules/load_failure.c19
-rw-r--r--test/Modules/lookup.cpp25
-rw-r--r--test/Modules/lookup.m19
-rw-r--r--test/Modules/macros.c41
-rw-r--r--test/Modules/module-private.cpp140
-rw-r--r--test/Modules/objc-categories.m89
-rw-r--r--test/Modules/on-demand-build-warnings.m5
-rw-r--r--test/Modules/on-demand-build.m17
-rw-r--r--test/Modules/on-demand-macros.m13
30 files changed, 519 insertions, 0 deletions
diff --git a/test/Modules/Inputs/CmdLine.framework/Headers/CmdLine.h b/test/Modules/Inputs/CmdLine.framework/Headers/CmdLine.h
new file mode 100644
index 0000000000000..46b8fc0425a64
--- /dev/null
+++ b/test/Modules/Inputs/CmdLine.framework/Headers/CmdLine.h
@@ -0,0 +1,6 @@
+#ifdef FOO_RETURNS_INT_PTR
+int *foo(void);
+#else
+float *foo(void);
+#endif
+
diff --git a/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h b/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h
new file mode 100644
index 0000000000000..fa40697745611
--- /dev/null
+++ b/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h
@@ -0,0 +1,3 @@
+#include <Module/Module.h>
+
+#define DEPENDS_ON_MODULE 1
diff --git a/test/Modules/Inputs/Module.framework/Headers/Module.h b/test/Modules/Inputs/Module.framework/Headers/Module.h
new file mode 100644
index 0000000000000..7c7ef6ea10e97
--- /dev/null
+++ b/test/Modules/Inputs/Module.framework/Headers/Module.h
@@ -0,0 +1,12 @@
+const char *getModuleVersion(void);
+
+#ifdef FOO
+# error Module should have been built without -DFOO
+#endif
+
+@interface Module
++(const char *)version; // retrieve module version
++alloc;
+@end
+
+#define MODULE_H_MACRO 1
diff --git a/test/Modules/Inputs/MutuallyRecursive1.framework/Headers/MutuallyRecursive1.h b/test/Modules/Inputs/MutuallyRecursive1.framework/Headers/MutuallyRecursive1.h
new file mode 100644
index 0000000000000..2a8282cc0119a
--- /dev/null
+++ b/test/Modules/Inputs/MutuallyRecursive1.framework/Headers/MutuallyRecursive1.h
@@ -0,0 +1,3 @@
+
+__import_module__ MutuallyRecursive2;
+
diff --git a/test/Modules/Inputs/MutuallyRecursive2.framework/Headers/MutuallyRecursive2.h b/test/Modules/Inputs/MutuallyRecursive2.framework/Headers/MutuallyRecursive2.h
new file mode 100644
index 0000000000000..98008533f3072
--- /dev/null
+++ b/test/Modules/Inputs/MutuallyRecursive2.framework/Headers/MutuallyRecursive2.h
@@ -0,0 +1,6 @@
+
+
+__import_module__ MutuallyRecursive1;
+
+
+
diff --git a/test/Modules/Inputs/diamond_bottom.h b/test/Modules/Inputs/diamond_bottom.h
new file mode 100644
index 0000000000000..e0b06d6cd972c
--- /dev/null
+++ b/test/Modules/Inputs/diamond_bottom.h
@@ -0,0 +1,4 @@
+__import_module__ diamond_left;
+__import_module__ diamond_right;
+
+char bottom(char *x);
diff --git a/test/Modules/Inputs/diamond_left.h b/test/Modules/Inputs/diamond_left.h
new file mode 100644
index 0000000000000..88cbf60977b3a
--- /dev/null
+++ b/test/Modules/Inputs/diamond_left.h
@@ -0,0 +1,9 @@
+__import_module__ diamond_top;
+
+float left(float *);
+
+int top_left(char *c);
+
+int left_and_right(int*);
+
+
diff --git a/test/Modules/Inputs/diamond_right.h b/test/Modules/Inputs/diamond_right.h
new file mode 100644
index 0000000000000..6f8bb82f8d240
--- /dev/null
+++ b/test/Modules/Inputs/diamond_right.h
@@ -0,0 +1,7 @@
+__import_module__ diamond_top;
+
+double right(double *);
+
+struct left_and_right {
+ int left, right;
+};
diff --git a/test/Modules/Inputs/diamond_top.h b/test/Modules/Inputs/diamond_top.h
new file mode 100644
index 0000000000000..34998cd4324b9
--- /dev/null
+++ b/test/Modules/Inputs/diamond_top.h
@@ -0,0 +1,4 @@
+int top(int *);
+
+int top_left(char *c);
+
diff --git a/test/Modules/Inputs/load_failure.h b/test/Modules/Inputs/load_failure.h
new file mode 100644
index 0000000000000..5bcb44dcb3dc9
--- /dev/null
+++ b/test/Modules/Inputs/load_failure.h
@@ -0,0 +1 @@
+int fail(int);
diff --git a/test/Modules/Inputs/lookup_left.h b/test/Modules/Inputs/lookup_left.h
new file mode 100644
index 0000000000000..01723d40aa7a8
--- /dev/null
+++ b/test/Modules/Inputs/lookup_left.h
@@ -0,0 +1,3 @@
+@interface A
+- (int)method;
+@end
diff --git a/test/Modules/Inputs/lookup_left.hpp b/test/Modules/Inputs/lookup_left.hpp
new file mode 100644
index 0000000000000..66d6206137b86
--- /dev/null
+++ b/test/Modules/Inputs/lookup_left.hpp
@@ -0,0 +1,5 @@
+int *f0(int*);
+
+#pragma weak weak_identifier // expected-warning{{weak identifier 'weak_identifier' never declared}}
+
+
diff --git a/test/Modules/Inputs/lookup_right.h b/test/Modules/Inputs/lookup_right.h
new file mode 100644
index 0000000000000..f8f0c97d68183
--- /dev/null
+++ b/test/Modules/Inputs/lookup_right.h
@@ -0,0 +1,5 @@
+
+@interface B
+- (double)method;
+@end
+
diff --git a/test/Modules/Inputs/lookup_right.hpp b/test/Modules/Inputs/lookup_right.hpp
new file mode 100644
index 0000000000000..884534747f69b
--- /dev/null
+++ b/test/Modules/Inputs/lookup_right.hpp
@@ -0,0 +1 @@
+float *f0(float*);
diff --git a/test/Modules/Inputs/point.h b/test/Modules/Inputs/point.h
new file mode 100644
index 0000000000000..eab23d5867a8b
--- /dev/null
+++ b/test/Modules/Inputs/point.h
@@ -0,0 +1,2 @@
+struct Point { int x, y; };
+
diff --git a/test/Modules/auto-module-import.c b/test/Modules/auto-module-import.c
new file mode 100644
index 0000000000000..018717423876e
--- /dev/null
+++ b/test/Modules/auto-module-import.c
@@ -0,0 +1,13 @@
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -F %S/Inputs -verify %s
+
+#include <DependsOnModule/DependsOnModule.h>
+
+#ifdef MODULE_H_MACRO
+# error MODULE_H_MACRO should have been hidden
+#endif
+
+#ifdef DEPENDS_ON_MODULE
+# error DEPENDS_ON_MODULE should have been hidden
+#endif
diff --git a/test/Modules/cycles.c b/test/Modules/cycles.c
new file mode 100644
index 0000000000000..8e3e9c6316175
--- /dev/null
+++ b/test/Modules/cycles.c
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-cache-path %t -F %S/Inputs %s 2>&1 | FileCheck %s
+
+__import_module__ MutuallyRecursive1;
+
+// FIXME: Lots of redundant diagnostics here, because the preprocessor
+// can't currently tell the parser not to try to load the module again.
+
+// CHECK: MutuallyRecursive2.h:3:19: fatal error: cyclic dependency in module 'MutuallyRecursive1': MutuallyRecursive1 -> MutuallyRecursive2 -> MutuallyRecursive1
+// CHECK: MutuallyRecursive1.h:2:19: fatal error: could not build module 'MutuallyRecursive2'
+// CHECK: cycles.c:4:19: fatal error: could not build module 'MutuallyRecursive1'
+
diff --git a/test/Modules/diamond.c b/test/Modules/diamond.c
new file mode 100644
index 0000000000000..482836c44978a
--- /dev/null
+++ b/test/Modules/diamond.c
@@ -0,0 +1,27 @@
+
+
+
+// in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}}
+
+__import_module__ diamond_bottom;
+
+void test_diamond(int i, float f, double d, char c) {
+ top(&i);
+ left(&f);
+ right(&d);
+ bottom(&c);
+ bottom(&d); // expected-warning{{incompatible pointer types passing 'double *' to parameter of type 'char *'}}
+
+ // Names in multiple places in the diamond.
+ top_left(&c);
+
+ left_and_right(&i);
+ struct left_and_right lr;
+ lr.left = 17;
+}
+
+// RUN: %clang_cc1 -emit-module -o %T/diamond_top.pcm %S/Inputs/diamond_top.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash -emit-module -o %T/diamond_left.pcm %S/Inputs/diamond_left.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash -emit-module -o %T/diamond_right.pcm %S/Inputs/diamond_right.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash -emit-module -o %T/diamond_bottom.pcm %S/Inputs/diamond_bottom.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash %s -verify
diff --git a/test/Modules/driver.c b/test/Modules/driver.c
new file mode 100644
index 0000000000000..de10cd0ceccad
--- /dev/null
+++ b/test/Modules/driver.c
@@ -0,0 +1,6 @@
+// RUN: %clang %s -### 2>&1 | FileCheck -check-prefix NO_MODULE_CACHE %s
+// RUN: %clang -fmodule-cache-path blarg %s -### 2>&1 | FileCheck -check-prefix WITH_MODULE_CACHE %s
+
+// CHECK-NO_MODULE_CACHE: {{clang.*"-fmodule-cache-path"}}
+
+// CHECK-WITH_MODULE_CACHE: {{clang.*"-fmodule-cache-path" "blarg"}}
diff --git a/test/Modules/header-import.m b/test/Modules/header-import.m
new file mode 100644
index 0000000000000..9996dc75c8b74
--- /dev/null
+++ b/test/Modules/header-import.m
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-cache-path %t -F %S/Inputs -I %S/Inputs -verify %s
+
+#import "point.h"
+__import_module__ Module;
+#import "point.h"
+
diff --git a/test/Modules/irgen.c b/test/Modules/irgen.c
new file mode 100644
index 0000000000000..0debf05f59349
--- /dev/null
+++ b/test/Modules/irgen.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-module -triple x86_64-apple-darwin10 -o %t/module.pcm -DBUILD_MODULE %s
+// RUN: %clang_cc1 -fmodule-cache-path %t -triple x86_64-apple-darwin10 -fdisable-module-hash -emit-llvm -o - %s | FileCheck %s
+
+#ifdef BUILD_MODULE
+static inline int triple(int x) { return x * 3; }
+#else
+__import_module__ module;
+
+// CHECK: define void @triple_value
+void triple_value(int *px) {
+ *px = triple(*px);
+}
+
+// CHECK: define internal i32 @triple(i32
+#endif
diff --git a/test/Modules/load_failure.c b/test/Modules/load_failure.c
new file mode 100644
index 0000000000000..d16bba7628b19
--- /dev/null
+++ b/test/Modules/load_failure.c
@@ -0,0 +1,19 @@
+#ifdef NONEXISTENT
+__import_module__ load_nonexistent;
+#endif
+
+#ifdef FAILURE
+__import_module__ load_failure;
+#endif
+
+// RUN: %clang_cc1 -x c++ -emit-module -o %T/load_failure.pcm %S/Inputs/load_failure.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash %s -DNONEXISTENT 2>&1 | FileCheck -check-prefix=CHECK-NONEXISTENT %s
+// CHECK-NONEXISTENT: load_failure.c:2:19: fatal error: module 'load_nonexistent' not found
+
+// RUN: not %clang_cc1 -fmodule-cache-path %T -fdisable-module-hash %s -DFAILURE 2> %t
+// RUN: FileCheck -check-prefix=CHECK-FAILURE %s < %t
+
+// FIXME: Clean up diagnostic text below and give it a location
+// CHECK-FAILURE: error: C99 was disabled in PCH file but is currently enabled
+
+
diff --git a/test/Modules/lookup.cpp b/test/Modules/lookup.cpp
new file mode 100644
index 0000000000000..d3245f2935f91
--- /dev/null
+++ b/test/Modules/lookup.cpp
@@ -0,0 +1,25 @@
+
+#define import __import_module__
+import lookup_left_cxx;
+#define IMPORT(X) __import_module__ X
+IMPORT(lookup_right_cxx);
+
+void test(int i, float f) {
+ // unqualified lookup
+ f0(&i);
+ f0(&f);
+
+ // qualified lookup into the translation unit
+ ::f0(&i);
+ ::f0(&f);
+}
+
+// RUN: %clang_cc1 -emit-module -x c++ -verify -o %T/lookup_left_cxx.pcm %S/Inputs/lookup_left.hpp
+// RUN: %clang_cc1 -emit-module -x c++ -o %T/lookup_right_cxx.pcm %S/Inputs/lookup_right.hpp
+// RUN: %clang_cc1 -x c++ -fmodule-cache-path %T -fdisable-module-hash %s -verify
+// RUN: %clang_cc1 -ast-print -x c++ -fmodule-cache-path %T -fdisable-module-hash %s | FileCheck -check-prefix=CHECK-PRINT %s
+
+// CHECK-PRINT: int *f0(int *);
+// CHECK-PRINT: float *f0(float *);
+// CHECK-PRINT: void test(int i, float f)
+
diff --git a/test/Modules/lookup.m b/test/Modules/lookup.m
new file mode 100644
index 0000000000000..d45f93661b9ac
--- /dev/null
+++ b/test/Modules/lookup.m
@@ -0,0 +1,19 @@
+
+// lookup_left.h: expected-note{{using}}
+// lookup_right.h: expected-note{{also found}}
+__import_module__ lookup_left_objc;
+__import_module__ lookup_right_objc;
+
+void test(id x) {
+ [x method]; // expected-warning{{multiple methods named 'method' found}}
+}
+
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_left_objc.pcm %S/Inputs/lookup_left.h
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_right_objc.pcm %S/Inputs/lookup_right.h
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %T -fdisable-module-hash -verify %s
+// RUN: %clang_cc1 -ast-print -x objective-c -fmodule-cache-path %T -fdisable-module-hash %s | FileCheck -check-prefix=CHECK-PRINT %s
+
+// CHECK-PRINT: - (int) method;
+// CHECK-PRINT: - (double) method
+// CHECK-PRINT: void test(id x)
+
diff --git a/test/Modules/macros.c b/test/Modules/macros.c
new file mode 100644
index 0000000000000..899c19bb29c97
--- /dev/null
+++ b/test/Modules/macros.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -emit-module -o %t/macros.pcm -DMODULE %s
+// RUN: %clang_cc1 -verify -fmodule-cache-path %t -fdisable-module-hash %s
+// RUN: %clang_cc1 -E -fmodule-cache-path %t -fdisable-module-hash %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
+
+#if defined(MODULE)
+#define INTEGER(X) int
+#define FLOAT float
+#define DOUBLE double
+
+#__export_macro__ INTEGER
+#__export_macro__ DOUBLE
+
+int (INTEGER);
+
+#else
+
+__import_module__ macros;
+
+#ifndef INTEGER
+# error INTEGER macro should be visible
+#endif
+
+#ifdef FLOAT
+# error FLOAT macro should not be visible
+#endif
+
+#ifdef MODULE
+# error MODULE macro should not be visible
+#endif
+
+// CHECK-PREPROCESSED: double d
+double d;
+DOUBLE *dp = &d;
+
+#__export_macro__ WIBBLE // expected-error{{no macro named 'WIBBLE' to export}}
+
+void f() {
+ // CHECK-PREPROCESSED: int i = INTEGER;
+ int i = INTEGER; // the value was exported, the macro was not.
+}
+#endif
diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp
new file mode 100644
index 0000000000000..7bd2a205c055b
--- /dev/null
+++ b/test/Modules/module-private.cpp
@@ -0,0 +1,140 @@
+// RUN: mkdir -p %t
+// RUN: %clang_cc1 -x c++ -emit-module -o %t/left.pcm %s -D MODULE_LEFT
+// RUN: %clang_cc1 -x c++ -emit-module -o %t/right.pcm %s -D MODULE_RIGHT
+// RUN: %clang_cc1 -fmodule-cache-path %t -fdisable-module-hash %s -verify
+
+#if defined(MODULE_LEFT)
+
+__module_private__ struct HiddenStruct;
+
+struct HiddenStruct {
+};
+
+
+int &f0(int);
+
+template<typename T>
+__module_private__ void f1(T*);
+
+template<typename T>
+void f1(T*);
+
+template<typename T>
+__module_private__ class vector;
+
+template<typename T>
+class vector {
+};
+
+vector<float> vec_float;
+
+typedef __module_private__ int Integer;
+typedef int Integer;
+
+#elif defined(MODULE_RIGHT)
+__module_private__ double &f0(double);
+double &f0(double);
+
+__module_private__ int hidden_var;
+
+inline void test_f0_in_right() {
+ double &dr = f0(hidden_var);
+}
+
+struct VisibleStruct {
+ __module_private__ int field;
+ __module_private__ virtual void setField(int f);
+};
+
+#else
+__import_module__ left;
+__import_module__ right;
+
+void test() {
+ int &ir = f0(1.0); // okay: f0() from 'right' is not visible
+}
+
+int test_broken() {
+ HiddenStruct hidden; // expected-error{{use of undeclared identifier 'HiddenStruct'}}
+
+ Integer i; // expected-error{{use of undeclared identifier 'Integer'}}
+
+ int *ip = 0;
+ f1(ip); // expected-error{{use of undeclared identifier 'f1'}}
+
+ vector<int> vec; // expected-error{{use of undeclared identifier 'vector'}} \
+ // expected-error{{expected '(' for function-style cast or type construction}} \
+ // expected-error{{use of undeclared identifier 'vec'}}
+
+ VisibleStruct vs;
+ vs.field = 0; // expected-error{{no member named 'field' in 'VisibleStruct'}}
+ vs.setField(1); // expected-error{{no member named 'setField' in 'VisibleStruct'}}
+
+ return hidden_var; // expected-error{{use of undeclared identifier 'hidden_var'}}
+}
+
+// Check for private redeclarations of public entities.
+template<typename T>
+class public_class_template; // expected-note{{previous declaration is here}}
+
+template<typename T>
+__module_private__ class public_class_template; // expected-error{{__module_private__ declaration of 'public_class_template' follows public declaration}}
+
+
+typedef int public_typedef; // expected-note{{previous declaration is here}}
+typedef __module_private__ int public_typedef; // expected-error{{__module_private__ declaration of 'public_typedef' follows public declaration}}
+
+extern int public_var; // expected-note{{previous declaration is here}}
+extern __module_private__ int public_var; // expected-error{{__module_private__ declaration of 'public_var' follows public declaration}}
+
+void public_func(); // expected-note{{previous declaration is here}}
+__module_private__ void public_func(); // expected-error{{__module_private__ declaration of 'public_func' follows public declaration}}
+
+template<typename T>
+void public_func_template(); // expected-note{{previous declaration is here}}
+template<typename T>
+__module_private__ void public_func_template(); // expected-error{{__module_private__ declaration of 'public_func_template' follows public declaration}}
+
+struct public_struct; // expected-note{{previous declaration is here}}
+__module_private__ struct public_struct; // expected-error{{__module_private__ declaration of 'public_struct' follows public declaration}}
+
+// Check for attempts to make specializations private
+template<> __module_private__ void public_func_template<int>(); // expected-error{{template specialization cannot be declared __module_private__}}
+
+template<typename T>
+struct public_class {
+ struct inner_struct;
+ static int static_var;
+
+ friend __module_private__ void public_func_friend();
+ friend __module_private__ struct public_struct_friend;
+};
+
+template<> __module_private__ struct public_class<int>::inner_struct { }; // expected-error{{member specialization cannot be declared __module_private__}}
+template<> __module_private__ int public_class<int>::static_var = 17; // expected-error{{member specialization cannot be declared __module_private__}}
+
+template<>
+__module_private__ struct public_class<float> { }; // expected-error{{template specialization cannot be declared __module_private__}}
+
+template<typename T>
+__module_private__ struct public_class<T *> { }; // expected-error{{partial specialization cannot be declared __module_private__}}
+
+// Check for attempts to make parameters and variables with automatic
+// storage module-private.
+
+void local_var_private(__module_private__ int param) { // expected-error{{parameter 'param' cannot be declared __module_private__}}
+ __module_private__ struct Local { int x, y; } local; //expected-error{{local variable 'local' cannot be declared __module_private__}}
+
+ __module_private__ struct OtherLocal { int x; }; // expected-error{{local struct cannot be declared __module_private__}}
+
+ typedef __module_private__ int local_typedef; // expected-error{{typedef 'local_typedef' cannot be declared __module_private__}}
+}
+
+// Check struct size
+struct LikeVisibleStruct {
+ int field;
+ virtual void setField(int f);
+};
+
+int check_struct_size[sizeof(VisibleStruct) == sizeof(LikeVisibleStruct)? 1 : -1];
+#endif
diff --git a/test/Modules/objc-categories.m b/test/Modules/objc-categories.m
new file mode 100644
index 0000000000000..87aaa5c12cae3
--- /dev/null
+++ b/test/Modules/objc-categories.m
@@ -0,0 +1,89 @@
+// RUN: mkdir -p %t
+// RUN: %clang_cc1 -emit-module -o %t/diamond_top.pcm %s -D MODULE_TOP
+// RUN: %clang_cc1 -fmodule-cache-path %t -fdisable-module-hash -emit-module -o %t/diamond_left.pcm %s -D MODULE_LEFT
+// RUN: %clang_cc1 -fmodule-cache-path %t -fdisable-module-hash -emit-module -o %t/diamond_right.pcm %s -D MODULE_RIGHT
+// RUN: %clang_cc1 -fmodule-cache-path %t -fdisable-module-hash -emit-module -o %t/diamond_bottom.pcm %s -D MODULE_BOTTOM
+// RUN: %clang_cc1 -fmodule-cache-path %t -fdisable-module-hash %s -verify
+
+/*============================================================================*/
+#ifdef MODULE_TOP
+
+@interface Foo
+@end
+
+@interface Foo(Top)
+-(void)top;
+@end
+
+/*============================================================================*/
+#elif defined(MODULE_LEFT)
+
+__import_module__ diamond_top;
+
+@interface Foo(Left)
+-(void)left;
+@end
+
+@interface LeftFoo
+-(void)left;
+@end
+
+@interface Foo(Duplicate) // expected-note {{previous definition}}
+@end
+
+@interface Foo(Duplicate)
+@end
+
+/*============================================================================*/
+#elif defined(MODULE_RIGHT)
+
+__import_module__ diamond_top;
+
+@interface Foo(Right1)
+-(void)right1;
+@end
+
+@interface Foo(Right2)
+-(void)right2;
+@end
+
+@interface Foo(Duplicate) // expected-warning {{duplicate definition of category}}
+@end
+
+/*============================================================================*/
+#elif defined(MODULE_BOTTOM)
+
+__import_module__ diamond_left;
+
+@interface Foo(Bottom)
+-(void)bottom;
+@end
+
+__import_module__ diamond_right;
+
+@interface LeftFoo(Bottom)
+-(void)bottom;
+@end
+
+/*============================================================================*/
+#else
+
+__import_module__ diamond_bottom;
+
+@interface Foo(Source)
+-(void)source;
+@end
+
+void test(Foo *foo, LeftFoo *leftFoo) {
+ [foo source];
+ [foo bottom];
+ [foo left];
+ [foo right1];
+ [foo right2];
+ [foo top];
+
+ [leftFoo left];
+ [leftFoo bottom];
+}
+
+#endif
diff --git a/test/Modules/on-demand-build-warnings.m b/test/Modules/on-demand-build-warnings.m
new file mode 100644
index 0000000000000..aa122dbd85590
--- /dev/null
+++ b/test/Modules/on-demand-build-warnings.m
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Wmodule-build -fmodule-cache-path %t -F %S/Inputs -verify %s
+
+__import_module__ Module; // expected-warning{{building module 'Module' from source}}
+
diff --git a/test/Modules/on-demand-build.m b/test/Modules/on-demand-build.m
new file mode 100644
index 0000000000000..649caa8a7d805
--- /dev/null
+++ b/test/Modules/on-demand-build.m
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -fmodule-cache-path %t -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -x objective-c++ -fmodule-cache-path %t -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -fmodule-cache-path %t -F %S/Inputs -verify %s
+#define FOO
+__import_module__ Module;
+@interface OtherClass
+@end
+// in module: expected-note{{class method 'alloc' is assumed to return an instance of its receiver type ('Module *')}}
+void test_getModuleVersion() {
+ const char *version = getModuleVersion();
+ const char *version2 = [Module version];
+
+ OtherClass *other = [Module alloc]; // expected-error{{init}}
+}
+
+
diff --git a/test/Modules/on-demand-macros.m b/test/Modules/on-demand-macros.m
new file mode 100644
index 0000000000000..96abb2331f100
--- /dev/null
+++ b/test/Modules/on-demand-macros.m
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-cache-path %t -F %S/Inputs -DFOO_RETURNS_INT_PTR -verify %s
+// RUN: %clang_cc1 -fmodule-cache-path %t -F %S/Inputs -verify %s
+
+__import_module__ CmdLine;
+
+void test() {
+#ifdef FOO_RETURNS_INT_PTR
+ int *ip = foo();
+#else
+ float *fp = foo();
+#endif
+}