More work toward having an access method for visible

conversion functions.

llvm-svn: 81618
This commit is contained in:
Fariborz Jahanian 2009-09-12 18:26:03 +00:00
parent f68f63b7cf
commit b394f50ac9
4 changed files with 93 additions and 45 deletions

View File

@ -351,6 +351,10 @@ class CXXRecordDecl : public RecordDecl {
/// type (or array thereof), each such class has a trivial destructor.
bool HasTrivialDestructor : 1;
/// ComputedVisibleConversions - True when visible conversion functions are
/// already computed and are available.
bool ComputedVisibleConversions : 1;
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
@ -386,7 +390,9 @@ class CXXRecordDecl : public RecordDecl {
/// RecordDecl from which the member class was instantiated.
llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
TemplateOrInstantiation;
void getNestedVisibleConversionFunctions(CXXRecordDecl *RD);
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@ -578,17 +584,14 @@ public:
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
OverloadedFunctionDecl *getVisibleConversionFunctions(ASTContext &Context,
CXXRecordDecl *RD);
OverloadedFunctionDecl *getVisibleConversionFunctions();
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
void addVisibleConversionFunction(ASTContext &Context,
CXXConversionDecl *ConvDecl);
void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
/// \brief Add a new conversion function template to the list of visible
/// conversion functions.
void addVisibleConversionFunction(ASTContext &Context,
FunctionTemplateDecl *ConvDecl);
void addVisibleConversionFunction(FunctionTemplateDecl *ConvDecl);
/// addConversionFunction - Add a new conversion function to the
/// list of conversion functions.

View File

@ -33,7 +33,8 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), Bases(0), NumBases(0), VBases(0), NumVBases(0),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Conversions(DC, DeclarationName()),
VisibleConversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
@ -283,22 +284,12 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
PlainOldData = false;
}
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
OverloadedFunctionDecl *
CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
CXXRecordDecl *RD) {
if (RD == this) {
// If root class, all conversions are visible.
if (RD->bases_begin() == RD->bases_end())
return &Conversions;
// If visible conversion list is already evaluated, return it.
if (VisibleConversions.function_begin()
!= VisibleConversions.function_end())
return &VisibleConversions;
}
QualType ClassType = Context.getTypeDeclType(this);
/// getNestedVisibleConversionFunctions - imports unique conversion
/// functions from base classes into the visible conversion function
/// list of the class 'RD'. This is a private helper method.
void
CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) {
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
OverloadedFunctionDecl *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
@ -306,24 +297,36 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) {
if (FunctionTemplateDecl *ConversionTemplate =
dyn_cast<FunctionTemplateDecl>(*Func)) {
RD->addVisibleConversionFunction(Context, ConversionTemplate);
continue;
}
CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
NamedDecl *Conv = Func->get();
bool Candidate = true;
// Only those conversions not exact match of conversions in current
// class are candidateconversion routines.
// FIXME. This is a O(n^2) algorithm.
if (RD != this) {
OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
QualType ConvType = Context.getCanonicalType(Conv->getType());
QualType ConvType;
FunctionDecl *FD;
if (FunctionTemplateDecl *ConversionTemplate =
dyn_cast<FunctionTemplateDecl>(Conv))
FD = ConversionTemplate->getTemplatedDecl();
else
FD = cast<FunctionDecl>(Conv);
ConvType = getASTContext().getCanonicalType(FD->getType());
for (OverloadedFunctionDecl::function_iterator
TFunc = TopConversions->function_begin(),
TFuncEnd = TopConversions->function_end();
TFunc != TFuncEnd; ++TFunc) {
CXXConversionDecl *TopConv = cast<CXXConversionDecl>(*TFunc);
QualType TConvType = Context.getCanonicalType(TopConv->getType());
NamedDecl *TopConv = TFunc->get();
FunctionDecl *TFD;
QualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
dyn_cast<FunctionTemplateDecl>(TopConv))
TFD = TConversionTemplate->getTemplatedDecl();
else
TFD = cast<FunctionDecl>(TopConv);
TConvType = getASTContext().getCanonicalType(TFD->getType());
if (ConvType == TConvType) {
Candidate = false;
break;
@ -331,11 +334,11 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
}
}
if (Candidate) {
if (FunctionTemplateDecl *ConversionTemplate
= Conv->getDescribedFunctionTemplate())
RD->addVisibleConversionFunction(Context, ConversionTemplate);
else if (!Conv->getPrimaryTemplate()) // ignore specializations
RD->addVisibleConversionFunction(Context, Conv);
if (FunctionTemplateDecl *ConversionTemplate =
dyn_cast<FunctionTemplateDecl>(Conv))
RD->addVisibleConversionFunction(ConversionTemplate);
else
RD->addVisibleConversionFunction(cast<CXXConversionDecl>(Conv));
}
}
}
@ -344,7 +347,7 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
E = vbases_end(); VBase != E; ++VBase) {
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
VBaseClassDecl->getVisibleConversionFunctions(Context, RD);
VBaseClassDecl->getNestedVisibleConversionFunctions(RD);
}
for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
E = bases_end(); Base != E; ++Base) {
@ -352,19 +355,33 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
continue;
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
BaseClassDecl->getVisibleConversionFunctions(Context, RD);
BaseClassDecl->getNestedVisibleConversionFunctions(RD);
}
}
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
OverloadedFunctionDecl *
CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
return &Conversions;
// If visible conversion list is already evaluated, return it.
if (ComputedVisibleConversions)
return &VisibleConversions;
getNestedVisibleConversionFunctions(this);
ComputedVisibleConversions = true;
return &VisibleConversions;
}
void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
VisibleConversions.addOverload(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");

View File

@ -739,7 +739,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
OverloadedFunctionDecl *Conversions =
RD->getVisibleConversionFunctions(Context, RD);
RD->getVisibleConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(),

View File

@ -43,7 +43,6 @@ void f2 (D2 d)
}
// Test4
struct B3 {
operator const int *();
};
@ -69,7 +68,6 @@ struct X {
void f4(X x) { delete x; delete x; }
// Test6
struct X1 {
operator int();
operator int*();
@ -78,6 +76,36 @@ struct X1 {
void f5(X1 x) { delete x; } // FIXME. May have to issue error here too.
// Test7
struct Base {
operator int*();
};
struct Derived : Base {
operator int*() const; // not the same function as Base's non-const operator int()
};
void foo6(const Derived cd) {
// FIXME. overload resolution must select Derived::operator int*() const;
delete cd; // expected-error {{cannot delete expression of type 'struct Derived const'}}
}
// Test8
struct BB {
template<typename T> operator T*() const;
};
struct DD : BB {
template<typename T> operator T*() const; // hides base conversion
operator int *() const;
};
void foo7 (DD d)
{
// FIXME. We select DD::operator int *() const; g++ issues ambiguity error. Investigate.
delete d;
}