From acd954bd8f28383e7538c4d0fd989763744f5e99 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 24 Jun 2013 04:45:28 +0000 Subject: [PATCH] Slightly improve cross-module merging for function templates. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184689 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReaderDecl.cpp | 19 ++++++++----- test/Modules/Inputs/cxx-templates-a.h | 6 ++++ test/Modules/Inputs/cxx-templates-b.h | 6 ++++ test/Modules/Inputs/module.map | 8 ++++++ test/Modules/cxx-templates.cpp | 41 +++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 test/Modules/Inputs/cxx-templates-a.h create mode 100644 test/Modules/Inputs/cxx-templates-b.h create mode 100644 test/Modules/cxx-templates.cpp diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index ffbff3882b..3d64fa51d9 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1815,10 +1815,10 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { (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(X)) { FunctionDecl *FuncY = cast(Y); return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) && @@ -1831,16 +1831,21 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { 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(X)) { NamespaceDecl *NamespaceY = cast(Y); return NamespaceX->isInline() == NamespaceY->isInline(); } - // Identical template names and kinds match. - if (isa(X)) - return true; + // Identical template names and kinds match if their template parameter lists + // and patterns match. + if (TemplateDecl *TemplateX = dyn_cast(X)) { + TemplateDecl *TemplateY = dyn_cast(Y); + // FIXME: Check template parameter lists. + return isSameEntity(TemplateX->getTemplatedDecl(), + TemplateY->getTemplatedDecl()); + } // FIXME: Many other cases to implement. return false; diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h new file mode 100644 index 0000000000..52bc3a2e3a --- /dev/null +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -0,0 +1,6 @@ +template T f() { return T(); } +template T f(T); +namespace N { + template T f() { return T(); } + template T f(T); +} diff --git a/test/Modules/Inputs/cxx-templates-b.h b/test/Modules/Inputs/cxx-templates-b.h new file mode 100644 index 0000000000..3cc940c2c4 --- /dev/null +++ b/test/Modules/Inputs/cxx-templates-b.h @@ -0,0 +1,6 @@ +template T f(); +template T f(T t) { return t; } +namespace N { + template T f(); + template T f(T t) { return t; } +} diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 65c75fdc1c..d2ed75830b 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -188,6 +188,14 @@ module cxx_linkage_cache { 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 diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp new file mode 100644 index 0000000000..bc96772083 --- /dev/null +++ b/test/Modules/cxx-templates.cpp @@ -0,0 +1,41 @@ +// 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(1.0); + f(); + 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(1.0); + N::f(); + 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' -- 2.40.0