forked from OSchip/llvm-project
More work toward having an access method for visible
conversion functions. llvm-svn: 81618
This commit is contained in:
parent
f68f63b7cf
commit
b394f50ac9
|
@ -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;
|
||||
|
@ -387,6 +391,8 @@ class CXXRecordDecl : public RecordDecl {
|
|||
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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue