When writing out the entries in a lookup table for a DeclContext, make

sure that all of the CXXConversionDecls go into the same
bucket. Otherwise, name lookup might not find them all. Fixes
<rdar://problem/10041960>.

llvm-svn: 138824
This commit is contained in:
Douglas Gregor 2011-08-30 20:49:19 +00:00
parent f3458e5594
commit 05ef93158d
3 changed files with 36 additions and 6 deletions

View File

@ -2624,14 +2624,37 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
ASTDeclContextNameLookupTrait Trait(*this);
// Create the on-disk hash table representation.
DeclarationName ConversionName;
llvm::SmallVector<NamedDecl *, 4> ConversionDecls;
for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
D != DEnd; ++D) {
DeclarationName Name = D->first;
DeclContext::lookup_result Result = D->second.getLookupResult();
if (Result.first != Result.second)
if (Result.first != Result.second) {
if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
// Hash all conversion function names to the same name. The actual
// type information in conversion function name is not used in the
// key (since such type information is not stable across different
// modules), so the intended effect is to coalesce all of the conversion
// functions under a single key.
if (!ConversionName)
ConversionName = Name;
ConversionDecls.append(Result.first, Result.second);
continue;
}
Generator.insert(Name, Result, Trait);
}
}
// Add the conversion functions
if (!ConversionDecls.empty()) {
Generator.insert(ConversionName,
DeclContext::lookup_result(ConversionDecls.begin(),
ConversionDecls.end()),
Trait);
}
// Create the on-disk hash table in a buffer.
llvm::SmallString<4096> LookupTable;
uint32_t BucketOffset;

View File

@ -0,0 +1,6 @@
struct S {
void m(int x);
operator const char*();
operator char*();
};

View File

@ -1,7 +1,8 @@
// RUN: %clang_cc1 -emit-pch %s -o %t
struct S {
void m(int x);
};
// RUN: %clang_cc1 -x c++ -emit-pch %S/Inputs/cxx-method.h -o %t
// RUN: %clang_cc1 -include-pch %t -verify %s
void S::m(int x) { }
S::operator char *() { return 0; }
S::operator const char *() { return 0; }