diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-11 21:44:33 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-11 21:44:33 +0000 |
commit | 5346278f81930e7fd0545bbbb2fc217c6921b109 (patch) | |
tree | cbd237e369e0bcde0fa6f98ef22e0dea91e26e01 /lib | |
parent | 52604ab71a74b8ec481255dfeea7dc9dba63b1a5 (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.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 6 |
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(); |