From: Richard Trieu Date: Thu, 22 Feb 2018 05:50:29 +0000 (+0000) Subject: [ODRHash] Fix hashing for friend functions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dbeaacc7e51d3cce6a9747bb7c8771e4b117cafe;p=clang [ODRHash] Fix hashing for friend functions. When hashing a templated function, use the hash of the function it was instantiated from. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325742 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 30599ea7cf..c4da87c013 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3625,6 +3625,12 @@ unsigned FunctionDecl::getODRHash() { } } + if (auto *FT = getInstantiatedFromMemberFunction()) { + HasODRHash = true; + ODRHash = FT->getODRHash(); + return ODRHash; + } + class ODRHash Hash; Hash.AddFunctionDecl(this); HasODRHash = true; diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 4104d3454e..528e32aaba 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -484,9 +484,6 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { if (!Function->hasBody()) return; if (!Function->getBody()) return; - // TODO: Fix hashing friend functions. - if (Function->getFriendObjectKind()) return; - // Skip functions that are specializations or in specialization context. const DeclContext *DC = Function; while (DC) { diff --git a/test/Modules/Inputs/odr_hash-Friend/Bad.h b/test/Modules/Inputs/odr_hash-Friend/Bad.h new file mode 100644 index 0000000000..c0a6d1f988 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-Friend/Bad.h @@ -0,0 +1,17 @@ +template +struct iterator { + void Compare(const iterator &x) { return; } + friend void Check(iterator) { return; } +}; + +template struct Box { + iterator I; + + void test() { + Check(I); + I.Compare(I); + } +}; + +// Force instantiation of Box +Box<> B; diff --git a/test/Modules/Inputs/odr_hash-Friend/Good.h b/test/Modules/Inputs/odr_hash-Friend/Good.h new file mode 100644 index 0000000000..4c38392eb6 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-Friend/Good.h @@ -0,0 +1,17 @@ +template +struct iterator { + void Compare(const iterator &x) { } + friend void Check(iterator) {} +}; + +template struct Box { + iterator I; + + void test() { + Check(I); + I.Compare(I); + } +}; + +// Force instantiation of Box +Box<> B; diff --git a/test/Modules/Inputs/odr_hash-Friend/module.modulemap b/test/Modules/Inputs/odr_hash-Friend/module.modulemap index 28e1832e30..449d51e7f7 100644 --- a/test/Modules/Inputs/odr_hash-Friend/module.modulemap +++ b/test/Modules/Inputs/odr_hash-Friend/module.modulemap @@ -13,3 +13,11 @@ module Module2 { module Module3 { header "M3.h" } + +module Good { + header "Good.h" +} + +module Bad { + header "Bad.h" +} diff --git a/test/Modules/odr_hash-Friend.cpp b/test/Modules/odr_hash-Friend.cpp index 39c0c4b762..8a2513e2f9 100644 --- a/test/Modules/odr_hash-Friend.cpp +++ b/test/Modules/odr_hash-Friend.cpp @@ -1,21 +1,89 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/modules.cache \ +// PR35939: MicrosoftMangle.cpp triggers an assertion failure on this test. +// UNSUPPORTED: system-windows + +// RUN: %clang_cc1 \ // RUN: -I %S/Inputs/odr_hash-Friend \ // RUN: -emit-obj -o /dev/null \ // RUN: -fmodules \ // RUN: -fimplicit-module-maps \ // RUN: -fmodules-cache-path=%t/modules.cache \ -// RUN: -std=c++11 -x c++ %s -verify +// RUN: -std=c++11 -x c++ %s -verify -DTEST1 -fcolor-diagnostics -// PR35939: MicrosoftMangle.cpp triggers an assertion failure on this test. -// UNSUPPORTED: system-windows +// RUN: %clang_cc1 \ +// RUN: -I %S/Inputs/odr_hash-Friend \ +// RUN: -emit-obj -o /dev/null \ +// RUN: -fmodules \ +// RUN: -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t/modules.cache \ +// RUN: -std=c++11 -x c++ %s -verify -DTEST2 -fcolor-diagnostics + +// RUN: %clang_cc1 \ +// RUN: -I %S/Inputs/odr_hash-Friend \ +// RUN: -emit-obj -o /dev/null \ +// RUN: -fmodules \ +// RUN: -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t/modules.cache \ +// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics + +// RUN: %clang_cc1 \ +// RUN: -I %S/Inputs/odr_hash-Friend \ +// RUN: -emit-obj -o /dev/null \ +// RUN: -fmodules \ +// RUN: -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t/modules.cache \ +// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics + +// RUN: %clang_cc1 \ +// RUN: -I %S/Inputs/odr_hash-Friend \ +// RUN: -emit-obj -o /dev/null \ +// RUN: -fmodules \ +// RUN: -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t/modules.cache \ +// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics +#if defined(TEST1) +#include "Box.h" +#include "M1.h" +#include "M3.h" // expected-no-diagnostics +#endif +#if defined(TEST2) #include "Box.h" #include "M1.h" #include "M3.h" +#include "Good.h" +// expected-no-diagnostics +#endif + +#if defined(TEST3) +#include "Good.h" +#include "Box.h" +#include "M1.h" +#include "M3.h" +// expected-no-diagnostics +#endif + +#if defined(TEST4) +#include "Box.h" +#include "M1.h" +#include "M3.h" +#include "Bad.h" +// expected-error@Bad.h:* {{'Check' has different definitions in different modules; definition in module 'Bad' first difference is function body}} +// expected-note@Box.h:* {{but in 'Box' found a different body}} +#endif + +#if defined(TEST5) +#include "Bad.h" +#include "Box.h" +#include "M1.h" +#include "M3.h" +// expected-error@Bad.h:* {{'Check' has different definitions in different modules; definition in module 'Bad' first difference is function body}} +// expected-note@Box.h:* {{but in 'Box' found a different body}} +#endif + void Run() { Box<> Present;