Move the management of the set of conversion functions in a C++ class

into CXXRecordDecl. The only part that we do not handle this way are
using declarations, since that would require extra name lookup that we
don't currently want to pay for. This fixes <rdar://problem/8459981>,
so that LLDB can build a CXXRecordDecl and magically get all of the
right bits set.

llvm-svn: 115026
This commit is contained in:
Douglas Gregor 2010-09-29 04:25:11 +00:00
parent 0be2dbb6a2
commit 457104e98b
3 changed files with 45 additions and 47 deletions

View File

@ -657,13 +657,6 @@ public:
return getConversionFunctions()->end();
}
/// Replaces a conversion function with a new declaration.
///
/// Returns true if the old conversion was found.
bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
return getConversionFunctions()->replace(Old, New);
}
/// Removes a conversion function from this class. The conversion
/// function must currently be a member of this class. Furthermore,
/// this class must currently be in the process of being defined.
@ -673,18 +666,6 @@ public:
/// in current class; including conversion function templates.
const UnresolvedSetImpl *getVisibleConversionFunctions();
/// addConversionFunction - Registers a conversion function which
/// this class declares directly.
void addConversionFunction(NamedDecl *Decl) {
#ifndef NDEBUG
CheckConversionFunction(Decl);
#endif
// We intentionally don't use the decl's access here because it
// hasn't been set yet. That's really just a misdesign in Sema.
data().Conversions.addDecl(Decl);
}
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
/// constructors, no private or protected non-static data members,

View File

@ -493,6 +493,30 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().PlainOldData = false;
}
// Keep the list of conversion functions up-to-date.
if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
// We don't record specializations.
if (Conversion->getPrimaryTemplate())
return;
// FIXME: We intentionally don't use the decl's access here because it
// hasn't been set yet. That's really just a misdesign in Sema.
if (FunTmpl) {
if (FunTmpl->getPreviousDeclaration())
data().Conversions.replace(FunTmpl->getPreviousDeclaration(),
FunTmpl);
else
data().Conversions.addDecl(FunTmpl);
} else {
if (Conversion->getPreviousDeclaration())
data().Conversions.replace(Conversion->getPreviousDeclaration(),
Conversion);
else
data().Conversions.addDecl(Conversion);
}
}
return;
}
@ -546,6 +570,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
}
}
// Handle using declarations of conversion functions.
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D))
if (Shadow->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName)
data().Conversions.addDecl(Shadow, Shadow->getAccess());
}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
@ -833,6 +863,12 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
}
}
}
// Set access bits correctly on the directly-declared conversions.
for (UnresolvedSetIterator I = data().Conversions.begin(),
E = data().Conversions.end();
I != E; ++I)
data().Conversions.setAccess(I, (*I)->getAccess());
}
bool CXXRecordDecl::mayBeAbstract() const {

View File

@ -3107,25 +3107,10 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
<< ClassType << ConvType;
}
if (Conversion->getPrimaryTemplate()) {
// ignore specializations
} else if (Conversion->getPreviousDeclaration()) {
if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate()) {
if (ClassDecl->replaceConversion(
ConversionTemplate->getPreviousDeclaration(),
ConversionTemplate))
return ConversionTemplate;
} else if (ClassDecl->replaceConversion(Conversion->getPreviousDeclaration(),
Conversion))
return Conversion;
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
} else if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
ClassDecl->addConversionFunction(ConversionTemplate);
else
ClassDecl->addConversionFunction(Conversion);
if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
return ConversionTemplate;
return Conversion;
}
@ -3669,20 +3654,16 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
= UsingShadowDecl::Create(Context, CurContext,
UD->getLocation(), UD, Target);
UD->addShadowDecl(Shadow);
Shadow->setAccess(UD->getAccess());
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
if (S)
PushOnScopeChains(Shadow, S);
else
CurContext->addDecl(Shadow);
Shadow->setAccess(UD->getAccess());
// Register it as a conversion if appropriate.
if (Shadow->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName)
cast<CXXRecordDecl>(CurContext)->addConversionFunction(Shadow);
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
return Shadow;
}