aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-09-11 21:44:33 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-09-11 21:44:33 +0000
commit5346278f81930e7fd0545bbbb2fc217c6921b109 (patch)
treecbd237e369e0bcde0fa6f98ef22e0dea91e26e01 /lib
parent52604ab71a74b8ec481255dfeea7dc9dba63b1a5 (diff)
Patch to build visible conversion function list lazily and make its
first use in calling the conversion function on delete statements. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81576 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclCXX.cpp84
-rw-r--r--lib/Sema/SemaExprCXX.cpp6
2 files changed, 87 insertions, 3 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 073ef947bf..e878a3df28 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -35,6 +35,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), Bases(0), NumBases(0), VBases(0), NumVBases(0),
Conversions(DC, DeclarationName()),
+ VisibleConversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -282,6 +283,89 @@ 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 visible conversion list is already evaluated, return it.
+ if (RD == this &&
+ VisibleConversions.function_begin() != VisibleConversions.function_end())
+ return &VisibleConversions;
+
+ QualType ClassType = Context.getTypeDeclType(this);
+ if (const RecordType *Record = ClassType->getAs<RecordType>()) {
+ OverloadedFunctionDecl *Conversions
+ = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+ for (OverloadedFunctionDecl::function_iterator
+ 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);
+ bool Candidate = true;
+ // Only those conversions not exact match of conversions in current
+ // class are candidateconversion routines.
+ if (RD != this) {
+ OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
+ QualType ConvType = Context.getCanonicalType(Conv->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());
+ if (ConvType == TConvType) {
+ Candidate = false;
+ break;
+ }
+ }
+ }
+ if (Candidate) {
+ if (FunctionTemplateDecl *ConversionTemplate
+ = Conv->getDescribedFunctionTemplate())
+ RD->addVisibleConversionFunction(Context, ConversionTemplate);
+ else if (!Conv->getPrimaryTemplate()) // ignore specializations
+ RD->addVisibleConversionFunction(Context, Conv);
+ }
+ }
+ }
+
+ for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
+ E = vbases_end(); VBase != E; ++VBase) {
+ CXXRecordDecl *VBaseClassDecl
+ = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+ VBaseClassDecl->getVisibleConversionFunctions(Context, RD);
+ }
+ for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
+ E = bases_end(); Base != E; ++Base) {
+ if (Base->isVirtual())
+ continue;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ BaseClassDecl->getVisibleConversionFunctions(Context, RD);
+ }
+ return &VisibleConversions;
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+ CXXConversionDecl *ConvDecl) {
+ assert(!ConvDecl->getDescribedFunctionTemplate() &&
+ "Conversion function templates should cast to FunctionTemplateDecl.");
+ VisibleConversions.addOverload(ConvDecl);
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+ FunctionTemplateDecl *ConvDecl) {
+ assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
+ "Function template is not a conversion function template");
+ VisibleConversions.addOverload(ConvDecl);
+}
+
void CXXRecordDecl::addConversionFunction(ASTContext &Context,
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index edf51cac6e..c6147ef269 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -736,11 +736,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Type = Ex->getType();
if (const RecordType *Record = Type->getAs<RecordType>()) {
- // FIXME: Inherited conversion functions!
llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ OverloadedFunctionDecl *Conversions =
+ RD->getVisibleConversionFunctions(Context, RD);
- OverloadedFunctionDecl *Conversions
- = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();