diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-07 20:43:36 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-07 20:43:36 +0000 |
commit | 0351a1e2e17c1edf27f90c23fbf65d8fcad995c4 (patch) | |
tree | c8ac743f00e74c097b13baf564c0692d73c25f3b /lib/AST | |
parent | 0a4074768a6ecd81513f0db02bfb0e96ab3e56a0 (diff) |
Fixes problem in finding visible convertion functions of a class
where matching conversion types in base classes were still visible.
Plus refactoring and cleanup.
Added a test case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83485 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index d1aef6a5b3..7408f2fc60 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -285,39 +285,45 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, PlainOldData = false; } +void +CXXRecordDecl::collectConversionFunctions( + llvm::SmallPtrSet<QualType, 8>& ConversionsTypeSet) { + OverloadedFunctionDecl *TopConversions = getConversionFunctions(); + for (OverloadedFunctionDecl::function_iterator + TFunc = TopConversions->function_begin(), + TFuncEnd = TopConversions->function_end(); + TFunc != TFuncEnd; ++TFunc) { + NamedDecl *TopConv = TFunc->get(); + QualType TConvType; + if (FunctionTemplateDecl *TConversionTemplate = + dyn_cast<FunctionTemplateDecl>(TopConv)) + TConvType = + getASTContext().getCanonicalType( + TConversionTemplate->getTemplatedDecl()->getResultType()); + else + TConvType = + getASTContext().getCanonicalType( + cast<CXXConversionDecl>(TopConv)->getConversionType()); + ConversionsTypeSet.insert(TConvType); + } +} + /// getNestedVisibleConversionFunctions - imports unique conversion /// functions from base classes into the visible conversion function /// list of the class 'RD'. This is a private helper method. +/// TopConversionsTypeSet is the set of conversion functions of the class +/// we are interested in. HiddenConversionTypes is set of conversion functions +/// of the immediate derived class which hides the conversion functions found +/// in current class. void -CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { +CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD, + const llvm::SmallPtrSet<QualType, 8> &TopConversionsTypeSet, + const llvm::SmallPtrSet<QualType, 8> &HiddenConversionTypes) { + bool inTopClass = (RD == this); QualType ClassType = getASTContext().getTypeDeclType(this); if (const RecordType *Record = ClassType->getAs<RecordType>()) { OverloadedFunctionDecl *Conversions = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); - llvm::SmallPtrSet<QualType, 8> TopConversionsTypeSet; - bool inTopClass = (RD == this); - if (!inTopClass && - (Conversions->function_begin() != Conversions->function_end())) { - // populate the TypeSet with the type of current class's conversions. - OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - TFunc = TopConversions->function_begin(), - TFuncEnd = TopConversions->function_end(); - TFunc != TFuncEnd; ++TFunc) { - NamedDecl *TopConv = TFunc->get(); - QualType TConvType; - if (FunctionTemplateDecl *TConversionTemplate = - dyn_cast<FunctionTemplateDecl>(TopConv)) - TConvType = - getASTContext().getCanonicalType( - TConversionTemplate->getTemplatedDecl()->getResultType()); - else - TConvType = - getASTContext().getCanonicalType( - cast<CXXConversionDecl>(TopConv)->getConversionType()); - TopConversionsTypeSet.insert(TConvType); - } - } for (OverloadedFunctionDecl::function_iterator Func = Conversions->function_begin(), @@ -336,7 +342,12 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { ConvType = getASTContext().getCanonicalType( cast<CXXConversionDecl>(Conv)->getConversionType()); - if (inTopClass || !TopConversionsTypeSet.count(ConvType)) { + // We only add conversion functions found in the base class if they + // are not hidden by those found in HiddenConversionTypes which are + // the conversion functions in its derived class. + if (inTopClass || + (!TopConversionsTypeSet.count(ConvType) && + !HiddenConversionTypes.count(ConvType)) ) { if (FunctionTemplateDecl *ConversionTemplate = dyn_cast<FunctionTemplateDecl>(Conv)) RD->addVisibleConversionFunction(ConversionTemplate); @@ -350,7 +361,17 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { E = vbases_end(); VBase != E; ++VBase) { CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - VBaseClassDecl->getNestedVisibleConversionFunctions(RD); + if (inTopClass) + VBaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + TopConversionsTypeSet); + else { + llvm::SmallPtrSet<QualType, 8> HiddenConversionTypes; + collectConversionFunctions(HiddenConversionTypes); + VBaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + HiddenConversionTypes); + } } for (CXXRecordDecl::base_class_iterator Base = bases_begin(), E = bases_end(); Base != E; ++Base) { @@ -358,7 +379,17 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { continue; CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - BaseClassDecl->getNestedVisibleConversionFunctions(RD); + if (inTopClass) + BaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + TopConversionsTypeSet); + else { + llvm::SmallPtrSet<QualType, 8> HiddenConversionTypes; + collectConversionFunctions(HiddenConversionTypes); + BaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + HiddenConversionTypes); + } } } @@ -372,7 +403,10 @@ CXXRecordDecl::getVisibleConversionFunctions() { // If visible conversion list is already evaluated, return it. if (ComputedVisibleConversions) return &VisibleConversions; - getNestedVisibleConversionFunctions(this); + llvm::SmallPtrSet<QualType, 8> TopConversionsTypeSet; + collectConversionFunctions(TopConversionsTypeSet); + getNestedVisibleConversionFunctions(this, TopConversionsTypeSet, + TopConversionsTypeSet); ComputedVisibleConversions = true; return &VisibleConversions; } |