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.
|
/// 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.
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue