diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 1d9bae5d3129..ff79f91e5db1 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3067,7 +3067,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, return true; } -/// Determine whether the two declarations refer to the same entity.pr +/// Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -3261,10 +3261,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && UX->isAccessDeclaration() == UY->isAccessDeclaration(); } - if (const auto *UX = dyn_cast(X)) + if (const auto *UX = dyn_cast(X)) { return isSameQualifier( UX->getQualifier(), cast(Y)->getQualifier()); + } + + // Using-pack declarations are only created by instantiation, and match if + // they're instantiated from matching UnresolvedUsing...Decls. + if (const auto *UX = dyn_cast(X)) { + return declaresSameEntity( + UX->getInstantiatedFromUsingDecl(), + cast(Y)->getInstantiatedFromUsingDecl()); + } // Namespace alias definitions with the same target match. if (const auto *NAX = dyn_cast(X)) { diff --git a/clang/test/Modules/Inputs/merge-using-decls/a.h b/clang/test/Modules/Inputs/merge-using-decls/a.h index 0fe0067bf23c..2469cbd7601f 100644 --- a/clang/test/Modules/Inputs/merge-using-decls/a.h +++ b/clang/test/Modules/Inputs/merge-using-decls/a.h @@ -1,6 +1,7 @@ struct X { int v; typedef int t; + void f(X); }; struct YA { @@ -8,6 +9,10 @@ struct YA { typedef int type; }; +struct Z { + void f(Z); +}; + template struct C : X, T { using T::value; using typename T::type; @@ -41,3 +46,10 @@ typedef C::type I; typedef D::type I; typedef E::type I; typedef F::type I; + +#if __cplusplus >= 201702L +template struct G : T... { + using T::f...; +}; +using Q = decltype(G()); +#endif diff --git a/clang/test/Modules/Inputs/merge-using-decls/b.h b/clang/test/Modules/Inputs/merge-using-decls/b.h index 5d112ffbfe96..be9bf240cceb 100644 --- a/clang/test/Modules/Inputs/merge-using-decls/b.h +++ b/clang/test/Modules/Inputs/merge-using-decls/b.h @@ -1,6 +1,7 @@ struct X { int v; typedef int t; + void f(X); }; struct YB { @@ -14,6 +15,10 @@ struct YBRev { int type; }; +struct Z { + void f(Z); +}; + template struct C : X, T { using T::value; using typename T::type; @@ -54,3 +59,10 @@ typedef E::type I; #endif typedef F::type I; + +#if __cplusplus >= 201702L +template struct G : T... { + using T::f...; +}; +using Q = decltype(G()); +#endif diff --git a/clang/test/Modules/merge-using-decls.cpp b/clang/test/Modules/merge-using-decls.cpp index 1ec9a9a17bde..e3bf977f0544 100644 --- a/clang/test/Modules/merge-using-decls.cpp +++ b/clang/test/Modules/merge-using-decls.cpp @@ -2,9 +2,11 @@ // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify %s -DORDER=1 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++98 %s -DORDER=1 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++11 %s -DORDER=1 +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++17 %s -DORDER=1 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify %s -DORDER=2 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++98 %s -DORDER=2 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++11 %s -DORDER=2 +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++17 %s -DORDER=2 #if ORDER == 1 #include "a.h" @@ -39,6 +41,19 @@ template int UseAll(); template int UseAll(); template int UseAll(); +#if __cplusplus >= 201702L +void use_g(Q q) { + q.f(q); // expected-error {{ambiguous}} +#if ORDER == 1 + // expected-note@a.h:* {{candidate function}} + // expected-note@a.h:* {{candidate function}} +#else + // expected-note@b.h:* {{candidate function}} + // expected-note@b.h:* {{candidate function}} +#endif +} +#endif + // Which of these two sets of diagnostics is chosen is not important. It's OK // if this varies with ORDER, but it must be consistent across runs. #if ORDER == 1