diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 84 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 6 |
2 files changed, 87 insertions, 3 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 073ef947bf8..e878a3df280 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index edf51cac6e7..c6147ef269b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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(); |

