(TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
TagY->getTagKind() == TTK_Interface));
}
-
+
// Functions with the same type and linkage match.
- // FIXME: This needs to cope with function templates, merging of
- //prototyped/non-prototyped functions, etc.
+ // FIXME: This needs to cope with function template specializations,
+ // merging of prototyped/non-prototyped functions, etc.
if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
FunctionDecl *FuncY = cast<FunctionDecl>(Y);
return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) &&
VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
}
-
+
// Namespaces with the same name and inlinedness match.
if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
return NamespaceX->isInline() == NamespaceY->isInline();
}
- // Identical template names and kinds match.
- if (isa<TemplateDecl>(X))
- return true;
+ // Identical template names and kinds match if their template parameter lists
+ // and patterns match.
+ if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) {
+ TemplateDecl *TemplateY = dyn_cast<TemplateDecl>(Y);
+ // FIXME: Check template parameter lists.
+ return isSameEntity(TemplateX->getTemplatedDecl(),
+ TemplateY->getTemplatedDecl());
+ }
// FIXME: Many other cases to implement.
return false;
--- /dev/null
+template<typename T> T f() { return T(); }
+template<typename T> T f(T);
+namespace N {
+ template<typename T> T f() { return T(); }
+ template<typename T> T f(T);
+}
--- /dev/null
+template<typename T> T f();
+template<typename T> T f(T t) { return t; }
+namespace N {
+ template<typename T> T f();
+ template<typename T> T f(T t) { return t; }
+}
header "cxx-linkage-cache.h"
}
+module cxx_templates_a {
+ header "cxx-templates-a.h"
+}
+
+module cxx_templates_b {
+ header "cxx-templates-b.h"
+}
+
module config {
header "config.h"
config_macros [exhaustive] WANT_FOO, WANT_BAR
--- /dev/null
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-lookups | FileCheck %s --check-prefix=CHECK-GLOBAL
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
+
+@import cxx_templates_a;
+@import cxx_templates_b;
+
+void g() {
+ f(0);
+ f<double>(1.0);
+ f<int>();
+ f(); // expected-error {{no matching function}}
+ // expected-note@Inputs/cxx-templates-b.h:1 {{couldn't infer template argument}}
+ // expected-note@Inputs/cxx-templates-b.h:2 {{requires single argument}}
+
+ N::f(0);
+ N::f<double>(1.0);
+ N::f<int>();
+ N::f(); // expected-error {{no matching function}}
+ // expected-note@Inputs/cxx-templates-a.h:4 {{couldn't infer template argument}}
+ // expected-note@Inputs/cxx-templates-a.h:5 {{requires 1 argument, but 0 were provided}}
+}
+
+// FIXME: There should only be two 'f's here.
+// CHECK-GLOBAL: DeclarationName 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-GLOBAL-NEXT: `-FunctionTemplate {{.*}} 'f'
+
+// FIXME: There should only be two 'f's here.
+// CHECK-NAMESPACE-N: DeclarationName 'f'
+// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
+// CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f'