From: Vassil Vassilev Date: Wed, 26 Oct 2016 10:24:29 +0000 (+0000) Subject: [modules] PR28812: Modules can return duplicate field decls. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f16d077f5a07462afb1efa63e507fe5e82968b3c;p=clang [modules] PR28812: Modules can return duplicate field decls. If two modules contain duplicate class definitions the lookup result can contain more than 2 elements. Sift the lookup results until we find a field decl. It is not necessary to do ODR checks in place as they done elsewhere. This should fix issues when compiling with libstdc++ 5.2 and 6.2. Patch developed in collaboration with Richard Smith! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285184 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f49525c6e4..518a780a4e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12321,13 +12321,20 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { // Lookup can return at most two results: the pattern for the field, or the // injected class name of the parent record. No other member can have the // same name as the field. - assert(!Lookup.empty() && Lookup.size() <= 2 && + // In modules mode, lookup can return multiple results (coming from + // different modules). + assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) && "more than two lookup results for field name"); FieldDecl *Pattern = dyn_cast(Lookup[0]); if (!Pattern) { assert(isa(Lookup[0]) && "cannot have other non-field member with same name"); - Pattern = cast(Lookup[1]); + for (auto L : Lookup) + if (isa(L)) { + Pattern = cast(L); + break; + } + assert(Pattern && "We must have set the Pattern!"); } if (InstantiateInClassInitializer(Loc, Field, Pattern, diff --git a/test/Modules/Inputs/PR28812/Textual.h b/test/Modules/Inputs/PR28812/Textual.h new file mode 100644 index 0000000000..769962e087 --- /dev/null +++ b/test/Modules/Inputs/PR28812/Textual.h @@ -0,0 +1,11 @@ +#ifndef T_H +#define T_H + +template struct VarStreamArray; + +template struct VarStreamArrayIterator { + VarStreamArrayIterator(VarStreamArray) {} + bool HasError{}; +}; + +#endif // T_H diff --git a/test/Modules/Inputs/PR28812/a.h b/test/Modules/Inputs/PR28812/a.h new file mode 100644 index 0000000000..0d9da60c91 --- /dev/null +++ b/test/Modules/Inputs/PR28812/a.h @@ -0,0 +1 @@ +#include "Textual.h" diff --git a/test/Modules/Inputs/PR28812/b.h b/test/Modules/Inputs/PR28812/b.h new file mode 100644 index 0000000000..0d9da60c91 --- /dev/null +++ b/test/Modules/Inputs/PR28812/b.h @@ -0,0 +1 @@ +#include "Textual.h" diff --git a/test/Modules/Inputs/PR28812/module.modulemap b/test/Modules/Inputs/PR28812/module.modulemap new file mode 100644 index 0000000000..d2d2b4a0c3 --- /dev/null +++ b/test/Modules/Inputs/PR28812/module.modulemap @@ -0,0 +1,6 @@ +module "A" { + header "a.h" +} +module "B" { + header "b.h" +} diff --git a/test/Modules/pr28812.cpp b/test/Modules/pr28812.cpp new file mode 100644 index 0000000000..78267d2a4b --- /dev/null +++ b/test/Modules/pr28812.cpp @@ -0,0 +1,22 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -I%S/Inputs/PR28812 -verify %s +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -fmodules -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t -I%S/Inputs/PR28812 -verify %s + +template struct VarStreamArrayIterator; +template +struct VarStreamArray { + typedef VarStreamArrayIterator Iterator; + Iterator begin() { return Iterator(*this); } +}; + +#include "Textual.h" + +#include "a.h" +#include "b.h" + +VarStreamArray a; +auto b = a.begin(); + +// expected-no-diagnostics +