forked from OSchip/llvm-project
Support for merging UsingPackDecls across modules.
Fixes a false-positive error if the same std::variant<...> type is instantiated across multiple modules.
This commit is contained in:
parent
f6b6e72143
commit
9ab5f76117
|
@ -3067,7 +3067,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
|
||||||
return true;
|
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) {
|
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
|
||||||
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
|
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()) &&
|
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
|
||||||
UX->isAccessDeclaration() == UY->isAccessDeclaration();
|
UX->isAccessDeclaration() == UY->isAccessDeclaration();
|
||||||
}
|
}
|
||||||
if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
|
if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) {
|
||||||
return isSameQualifier(
|
return isSameQualifier(
|
||||||
UX->getQualifier(),
|
UX->getQualifier(),
|
||||||
cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
|
cast<UnresolvedUsingTypenameDecl>(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<UsingPackDecl>(X)) {
|
||||||
|
return declaresSameEntity(
|
||||||
|
UX->getInstantiatedFromUsingDecl(),
|
||||||
|
cast<UsingPackDecl>(Y)->getInstantiatedFromUsingDecl());
|
||||||
|
}
|
||||||
|
|
||||||
// Namespace alias definitions with the same target match.
|
// Namespace alias definitions with the same target match.
|
||||||
if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
|
if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
struct X {
|
struct X {
|
||||||
int v;
|
int v;
|
||||||
typedef int t;
|
typedef int t;
|
||||||
|
void f(X);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct YA {
|
struct YA {
|
||||||
|
@ -8,6 +9,10 @@ struct YA {
|
||||||
typedef int type;
|
typedef int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Z {
|
||||||
|
void f(Z);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> struct C : X, T {
|
template<typename T> struct C : X, T {
|
||||||
using T::value;
|
using T::value;
|
||||||
using typename T::type;
|
using typename T::type;
|
||||||
|
@ -41,3 +46,10 @@ typedef C<YA>::type I;
|
||||||
typedef D<YA>::type I;
|
typedef D<YA>::type I;
|
||||||
typedef E<YA>::type I;
|
typedef E<YA>::type I;
|
||||||
typedef F<YA>::type I;
|
typedef F<YA>::type I;
|
||||||
|
|
||||||
|
#if __cplusplus >= 201702L
|
||||||
|
template<typename ...T> struct G : T... {
|
||||||
|
using T::f...;
|
||||||
|
};
|
||||||
|
using Q = decltype(G<X, Z>());
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
struct X {
|
struct X {
|
||||||
int v;
|
int v;
|
||||||
typedef int t;
|
typedef int t;
|
||||||
|
void f(X);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct YB {
|
struct YB {
|
||||||
|
@ -14,6 +15,10 @@ struct YBRev {
|
||||||
int type;
|
int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Z {
|
||||||
|
void f(Z);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> struct C : X, T {
|
template<typename T> struct C : X, T {
|
||||||
using T::value;
|
using T::value;
|
||||||
using typename T::type;
|
using typename T::type;
|
||||||
|
@ -54,3 +59,10 @@ typedef E<YB>::type I;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef F<YB>::type I;
|
typedef F<YB>::type I;
|
||||||
|
|
||||||
|
#if __cplusplus >= 201702L
|
||||||
|
template<typename ...T> struct G : T... {
|
||||||
|
using T::f...;
|
||||||
|
};
|
||||||
|
using Q = decltype(G<X, Z>());
|
||||||
|
#endif
|
||||||
|
|
|
@ -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 %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++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++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 %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++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++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
|
#if ORDER == 1
|
||||||
#include "a.h"
|
#include "a.h"
|
||||||
|
@ -39,6 +41,19 @@ template int UseAll<YA>();
|
||||||
template int UseAll<YB>();
|
template int UseAll<YB>();
|
||||||
template int UseAll<Y>();
|
template int UseAll<Y>();
|
||||||
|
|
||||||
|
#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
|
// 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 this varies with ORDER, but it must be consistent across runs.
|
||||||
#if ORDER == 1
|
#if ORDER == 1
|
||||||
|
|
Loading…
Reference in New Issue