[modules] Make IndirectFieldDecl mergeable to avoid lookup ambiguity when the same anonymous union is defined across multiple modules.

llvm-svn: 243940
This commit is contained in:
Richard Smith 2015-08-04 02:05:09 +00:00
parent 215df9ed98
commit 8cbd895947
4 changed files with 23 additions and 1 deletions

View File

@ -2499,7 +2499,8 @@ public:
/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
class IndirectFieldDecl : public ValueDecl {
class IndirectFieldDecl : public ValueDecl,
public Mergeable<IndirectFieldDecl> {
void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
@ -2537,6 +2538,9 @@ public:
return dyn_cast<VarDecl>(*chain_begin());
}
IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == IndirectField; }

View File

@ -1178,6 +1178,8 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
for (unsigned I = 0; I != FD->ChainingSize; ++I)
FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
mergeMergeable(FD);
}
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
@ -2638,6 +2640,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
// Indirect fields with the same target field match.
if (auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
auto *IFDY = cast<IndirectFieldDecl>(Y);
return IFDX->getAnonField()->getCanonicalDecl() ==
IFDY->getAnonField()->getCanonicalDecl();
}
// Enumerators with the same name match.
if (isa<EnumConstantDecl>(X))
// FIXME: Also check the value is odr-equivalent.

View File

@ -103,3 +103,11 @@ namespace RedeclDifferentDeclKind {
typedef X X;
using RedeclDifferentDeclKind::X;
}
namespace Anon {
struct X {
union {
int n;
};
};
}

View File

@ -104,6 +104,7 @@ template<typename T, int N, template<typename> class K> struct J;
J<> post_j2;
FriendDefArg::Y<int> friend_def_arg;
FriendDefArg::D<> friend_def_arg_d;
int post_anon_x_n = Anon::X().n;
MergeFunctionTemplateSpecializations::X<int>::Q<char> xiqc;