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. /// type (or array thereof), each such class has a trivial destructor.
bool HasTrivialDestructor : 1; bool HasTrivialDestructor : 1;
/// ComputedVisibleConversions - True when visible conversion functions are
/// already computed and are available.
bool ComputedVisibleConversions : 1;
/// Bases - Base classes of this class. /// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union. /// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases; CXXBaseSpecifier *Bases;
@ -387,6 +391,8 @@ class CXXRecordDecl : public RecordDecl {
llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*> llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
TemplateOrInstantiation; TemplateOrInstantiation;
void getNestedVisibleConversionFunctions(CXXRecordDecl *RD);
protected: protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, SourceLocation L, IdentifierInfo *Id,
@ -578,17 +584,14 @@ public:
/// getVisibleConversionFunctions - get all conversion functions visible /// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates. /// in current class; including conversion function templates.
OverloadedFunctionDecl *getVisibleConversionFunctions(ASTContext &Context, OverloadedFunctionDecl *getVisibleConversionFunctions();
CXXRecordDecl *RD);
/// addVisibleConversionFunction - Add a new conversion function to the /// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions. /// list of visible conversion functions.
void addVisibleConversionFunction(ASTContext &Context, void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
CXXConversionDecl *ConvDecl);
/// \brief Add a new conversion function template to the list of visible /// \brief Add a new conversion function template to the list of visible
/// conversion functions. /// conversion functions.
void addVisibleConversionFunction(ASTContext &Context, void addVisibleConversionFunction(FunctionTemplateDecl *ConvDecl);
FunctionTemplateDecl *ConvDecl);
/// addConversionFunction - Add a new conversion function to the /// addConversionFunction - Add a new conversion function to the
/// list of conversion functions. /// 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), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), HasTrivialConstructor(true), Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(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()), Conversions(DC, DeclarationName()),
VisibleConversions(DC, DeclarationName()), VisibleConversions(DC, DeclarationName()),
TemplateOrInstantiation() { } TemplateOrInstantiation() { }
@ -283,22 +284,12 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
PlainOldData = false; PlainOldData = false;
} }
/// getVisibleConversionFunctions - get all conversion functions visible /// getNestedVisibleConversionFunctions - imports unique conversion
/// in current class; including conversion function templates. /// functions from base classes into the visible conversion function
OverloadedFunctionDecl * /// list of the class 'RD'. This is a private helper method.
CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context, void
CXXRecordDecl *RD) { CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) {
if (RD == this) { QualType ClassType = getASTContext().getTypeDeclType(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);
if (const RecordType *Record = ClassType->getAs<RecordType>()) { if (const RecordType *Record = ClassType->getAs<RecordType>()) {
OverloadedFunctionDecl *Conversions OverloadedFunctionDecl *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
@ -306,24 +297,36 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
Func = Conversions->function_begin(), Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end(); FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) { Func != FuncEnd; ++Func) {
if (FunctionTemplateDecl *ConversionTemplate = NamedDecl *Conv = Func->get();
dyn_cast<FunctionTemplateDecl>(*Func)) {
RD->addVisibleConversionFunction(Context, ConversionTemplate);
continue;
}
CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
bool Candidate = true; bool Candidate = true;
// Only those conversions not exact match of conversions in current // Only those conversions not exact match of conversions in current
// class are candidateconversion routines. // class are candidateconversion routines.
// FIXME. This is a O(n^2) algorithm.
if (RD != this) { if (RD != this) {
OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions(); 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 for (OverloadedFunctionDecl::function_iterator
TFunc = TopConversions->function_begin(), TFunc = TopConversions->function_begin(),
TFuncEnd = TopConversions->function_end(); TFuncEnd = TopConversions->function_end();
TFunc != TFuncEnd; ++TFunc) { 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) { if (ConvType == TConvType) {
Candidate = false; Candidate = false;
break; break;
@ -331,11 +334,11 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
} }
} }
if (Candidate) { if (Candidate) {
if (FunctionTemplateDecl *ConversionTemplate if (FunctionTemplateDecl *ConversionTemplate =
= Conv->getDescribedFunctionTemplate()) dyn_cast<FunctionTemplateDecl>(Conv))
RD->addVisibleConversionFunction(Context, ConversionTemplate); RD->addVisibleConversionFunction(ConversionTemplate);
else if (!Conv->getPrimaryTemplate()) // ignore specializations else
RD->addVisibleConversionFunction(Context, Conv); RD->addVisibleConversionFunction(cast<CXXConversionDecl>(Conv));
} }
} }
} }
@ -344,7 +347,7 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
E = vbases_end(); VBase != E; ++VBase) { E = vbases_end(); VBase != E; ++VBase) {
CXXRecordDecl *VBaseClassDecl CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
VBaseClassDecl->getVisibleConversionFunctions(Context, RD); VBaseClassDecl->getNestedVisibleConversionFunctions(RD);
} }
for (CXXRecordDecl::base_class_iterator Base = bases_begin(), for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
E = bases_end(); Base != E; ++Base) { E = bases_end(); Base != E; ++Base) {
@ -352,19 +355,33 @@ CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
continue; continue;
CXXRecordDecl *BaseClassDecl CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); = 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; return &VisibleConversions;
} }
void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context, void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) { CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() && assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl."); "Conversion function templates should cast to FunctionTemplateDecl.");
VisibleConversions.addOverload(ConvDecl); VisibleConversions.addOverload(ConvDecl);
} }
void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context, void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) { FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) && assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template"); "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; llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
OverloadedFunctionDecl *Conversions = OverloadedFunctionDecl *Conversions =
RD->getVisibleConversionFunctions(Context, RD); RD->getVisibleConversionFunctions();
for (OverloadedFunctionDecl::function_iterator for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(), Func = Conversions->function_begin(),

View File

@ -43,7 +43,6 @@ void f2 (D2 d)
} }
// Test4 // Test4
struct B3 { struct B3 {
operator const int *(); operator const int *();
}; };
@ -69,7 +68,6 @@ struct X {
void f4(X x) { delete x; delete x; } void f4(X x) { delete x; delete x; }
// Test6 // Test6
struct X1 { struct X1 {
operator int(); operator int();
operator int*(); operator int*();
@ -78,6 +76,36 @@ struct X1 {
void f5(X1 x) { delete x; } // FIXME. May have to issue error here too. 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;
}