summaryrefslogtreecommitdiffstats
path: root/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-04-02 08:55:10 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-04-02 08:55:10 +0000
commit07b2cfcdb817cc0790420f159a313d61e7241cb9 (patch)
treed374cdca417e76f1bf101f139dba2db1d10ee8f7 /lib/AST/DeclCXX.cpp
parent1e255aab650a7fa2047fd953cae65b12215280af (diff)
downloadFreeBSD-src-07b2cfcdb817cc0790420f159a313d61e7241cb9.zip
FreeBSD-src-07b2cfcdb817cc0790420f159a313d61e7241cb9.tar.gz
Update clang to r100181.
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r--lib/AST/DeclCXX.cpp133
1 files changed, 71 insertions, 62 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 37f7479..94ed85c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -83,9 +83,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (data().Bases)
C.Deallocate(data().Bases);
- int vbaseCount = 0;
- llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
- bool hasDirectVirtualBase = false;
+ // The set of seen virtual base types.
+ llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
+
+ // The virtual bases of this class.
+ llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases;
data().Bases = new(C) CXXBaseSpecifier [NumBases];
data().NumBases = NumBases;
@@ -99,58 +101,44 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
continue;
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- if (Base->isVirtual())
- hasDirectVirtualBase = true;
+
+ // Now go through all virtual bases of this base and add them.
for (CXXRecordDecl::base_class_iterator VBase =
BaseClassDecl->vbases_begin(),
E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) {
- // Add this vbase to the array of vbases for current class if it is
- // not already in the list.
- // FIXME. Note that we do a linear search as number of such classes are
- // very few.
- int i;
- for (i = 0; i < vbaseCount; ++i)
- if (UniqueVbases[i]->getType() == VBase->getType())
- break;
- if (i == vbaseCount) {
- UniqueVbases.push_back(VBase);
- ++vbaseCount;
- }
+ // Add this base if it's not already in the list.
+ if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType())))
+ VBases.push_back(VBase);
}
- }
- if (hasDirectVirtualBase) {
- // Iterate one more time through the direct bases and add the virtual
- // base to the list of vritual bases for current class.
- for (unsigned i = 0; i < NumBases; ++i) {
- const CXXBaseSpecifier *VBase = Bases[i];
- if (!VBase->isVirtual())
- continue;
- int j;
- for (j = 0; j < vbaseCount; ++j)
- if (UniqueVbases[j]->getType() == VBase->getType())
- break;
- if (j == vbaseCount) {
- UniqueVbases.push_back(VBase);
- ++vbaseCount;
- }
+
+ if (Base->isVirtual()) {
+ // Add this base if it's not already in the list.
+ if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)))
+ VBases.push_back(Base);
}
+
}
- if (vbaseCount > 0) {
- // build AST for inhireted, direct or indirect, virtual bases.
- data().VBases = new (C) CXXBaseSpecifier [vbaseCount];
- data().NumVBases = vbaseCount;
- for (int i = 0; i < vbaseCount; i++) {
- QualType QT = UniqueVbases[i]->getType();
- // Skip dependent types; we can't do any checking on them now.
- if (QT->isDependentType())
- continue;
- CXXRecordDecl *VBaseClassDecl
- = cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl());
- data().VBases[i] =
- CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
- VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
- UniqueVbases[i]->getAccessSpecifier(), QT);
- }
+
+ if (VBases.empty())
+ return;
+
+ // Create base specifier for any direct or indirect virtual bases.
+ data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
+ data().NumVBases = VBases.size();
+ for (int I = 0, E = VBases.size(); I != E; ++I) {
+ QualType VBaseType = VBases[I]->getType();
+
+ // Skip dependent types; we can't do any checking on them now.
+ if (VBaseType->isDependentType())
+ continue;
+
+ CXXRecordDecl *VBaseClassDecl
+ = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+
+ data().VBases[I] =
+ CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
+ VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
+ VBases[I]->getAccessSpecifier(), VBaseType);
}
}
@@ -320,6 +308,8 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
+ if (isa<UsingShadowDecl>(Conv))
+ Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl();
if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
T = ConvTemp->getTemplatedDecl()->getResultType();
else
@@ -457,26 +447,45 @@ const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
return &data().VisibleConversions;
}
-void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
- assert(!ConvDecl->getDescribedFunctionTemplate() &&
- "Conversion function templates should cast to FunctionTemplateDecl.");
+#ifndef NDEBUG
+void CXXRecordDecl::CheckConversionFunction(NamedDecl *ConvDecl) {
assert(ConvDecl->getDeclContext() == this &&
"conversion function does not belong to this record");
- // We intentionally don't use the decl's access here because it
- // hasn't been set yet. That's really just a misdesign in Sema.
- data().Conversions.addDecl(ConvDecl);
+ ConvDecl = ConvDecl->getUnderlyingDecl();
+ if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(ConvDecl)) {
+ assert(isa<CXXConversionDecl>(Temp->getTemplatedDecl()));
+ } else {
+ assert(isa<CXXConversionDecl>(ConvDecl));
+ }
}
+#endif
+
+void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
+ // This operation is O(N) but extremely rare. Sema only uses it to
+ // remove UsingShadowDecls in a class that were followed by a direct
+ // declaration, e.g.:
+ // class A : B {
+ // using B::operator int;
+ // operator int();
+ // };
+ // This is uncommon by itself and even more uncommon in conjunction
+ // with sufficiently large numbers of directly-declared conversions
+ // that asymptotic behavior matters.
+
+ UnresolvedSetImpl &Convs = *getConversionFunctions();
+ for (unsigned I = 0, E = Convs.size(); I != E; ++I) {
+ if (Convs[I].getDecl() == ConvDecl) {
+ Convs.erase(I);
+ assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end()
+ && "conversion was found multiple times in unresolved set");
+ return;
+ }
+ }
-void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
- assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
- "Function template is not a conversion function template");
- assert(ConvDecl->getDeclContext() == this &&
- "conversion function does not belong to this record");
- data().Conversions.addDecl(ConvDecl);
+ llvm_unreachable("conversion not found in set!");
}
-
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
setAggregate(false);
OpenPOWER on IntegriCloud