[cfe-commits] r104938 - /cfe/trunk/lib/Sema/SemaLookup.cpp
John McCall
rjmccall at apple.com
Thu May 27 23:08:54 PDT 2010
Author: rjmccall
Date: Fri May 28 01:08:54 2010
New Revision: 104938
URL: http://llvm.org/viewvc/llvm-project?rev=104938&view=rev
Log:
Optimize and complete associated-class-and-namespace collection from
a type.
Modified:
cfe/trunk/lib/Sema/SemaLookup.cpp
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=104938&r1=104937&r2=104938&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri May 28 01:08:54 2010
@@ -1590,7 +1590,7 @@
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
-addAssociatedClassesAndNamespaces(QualType T,
+addAssociatedClassesAndNamespaces(QualType Ty,
ASTContext &Context,
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
Sema::AssociatedClassSet &AssociatedClasses) {
@@ -1604,109 +1604,139 @@
// argument). Typedef names and using-declarations used to specify
// the types do not contribute to this set. The sets of namespaces
// and classes are determined in the following way:
- T = Context.getCanonicalType(T).getUnqualifiedType();
- // -- If T is a pointer to U or an array of U, its associated
- // namespaces and classes are those associated with U.
- //
- // We handle this by unwrapping pointer and array types immediately,
- // to avoid unnecessary recursion.
+ llvm::SmallVector<const Type *, 16> Queue;
+ const Type *T = Ty->getCanonicalTypeInternal().getTypePtr();
+
while (true) {
- if (const PointerType *Ptr = T->getAs<PointerType>())
- T = Ptr->getPointeeType();
- else if (const ArrayType *Ptr = Context.getAsArrayType(T))
- T = Ptr->getElementType();
- else
+ switch (T->getTypeClass()) {
+
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ // T is canonical. We can also ignore dependent types because
+ // we don't need to do ADL at the definition point, but if we
+ // wanted to implement template export (or if we find some other
+ // use for associated classes and namespaces...) this would be
+ // wrong.
break;
- }
- // -- If T is a fundamental type, its associated sets of
- // namespaces and classes are both empty.
- if (T->getAs<BuiltinType>())
- return;
+ // -- If T is a pointer to U or an array of U, its associated
+ // namespaces and classes are those associated with U.
+ case Type::Pointer:
+ T = cast<PointerType>(T)->getPointeeType().getTypePtr();
+ continue;
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ T = cast<ArrayType>(T)->getElementType().getTypePtr();
+ continue;
+
+ // -- If T is a fundamental type, its associated sets of
+ // namespaces and classes are both empty.
+ case Type::Builtin:
+ break;
- // -- If T is a class type (including unions), its associated
- // classes are: the class itself; the class of which it is a
- // member, if any; and its direct and indirect base
- // classes. Its associated namespaces are the namespaces in
- // which its associated classes are defined.
- if (const RecordType *ClassType = T->getAs<RecordType>())
- if (CXXRecordDecl *ClassDecl
- = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
- addAssociatedClassesAndNamespaces(ClassDecl, Context,
+ // -- If T is a class type (including unions), its associated
+ // classes are: the class itself; the class of which it is a
+ // member, if any; and its direct and indirect base
+ // classes. Its associated namespaces are the namespaces in
+ // which its associated classes are defined.
+ case Type::Record: {
+ CXXRecordDecl *Class
+ = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ addAssociatedClassesAndNamespaces(Class, Context,
AssociatedNamespaces,
AssociatedClasses);
- return;
+ break;
}
- // -- If T is an enumeration type, its associated namespace is
- // the namespace in which it is defined. If it is class
- // member, its associated class is the memberâs class; else
- // it has no associated class.
- if (const EnumType *EnumT = T->getAs<EnumType>()) {
- EnumDecl *Enum = EnumT->getDecl();
-
- DeclContext *Ctx = Enum->getDeclContext();
- if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
- AssociatedClasses.insert(EnclosingClass);
+ // -- If T is an enumeration type, its associated namespace is
+ // the namespace in which it is defined. If it is class
+ // member, its associated class is the memberâs class; else
+ // it has no associated class.
+ case Type::Enum: {
+ EnumDecl *Enum = cast<EnumType>(T)->getDecl();
+
+ DeclContext *Ctx = Enum->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ AssociatedClasses.insert(EnclosingClass);
- // Add the associated namespace for this class.
- CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
- return;
- }
+ break;
+ }
- // -- If T is a function type, its associated namespaces and
- // classes are those associated with the function parameter
- // types and those associated with the return type.
- if (const FunctionType *FnType = T->getAs<FunctionType>()) {
- // Return type
- addAssociatedClassesAndNamespaces(FnType->getResultType(),
- Context,
- AssociatedNamespaces, AssociatedClasses);
+ // -- If T is a function type, its associated namespaces and
+ // classes are those associated with the function parameter
+ // types and those associated with the return type.
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ Queue.push_back(Arg->getTypePtr());
+ // fallthrough
+ }
+ case Type::FunctionNoProto: {
+ const FunctionType *FnType = cast<FunctionType>(T);
+ T = FnType->getResultType().getTypePtr();
+ continue;
+ }
- const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
- if (!Proto)
- return;
+ // -- If T is a pointer to a member function of a class X, its
+ // associated namespaces and classes are those associated
+ // with the function parameter types and return type,
+ // together with those associated with X.
+ //
+ // -- If T is a pointer to a data member of class X, its
+ // associated namespaces and classes are those associated
+ // with the member type together with those associated with
+ // X.
+ case Type::MemberPointer: {
+ const MemberPointerType *MemberPtr = cast<MemberPointerType>(T);
- // Argument types
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- addAssociatedClassesAndNamespaces(*Arg, Context,
- AssociatedNamespaces, AssociatedClasses);
+ // Queue up the class type into which this points.
+ Queue.push_back(MemberPtr->getClass());
- return;
- }
+ // And directly continue with the pointee type.
+ T = MemberPtr->getPointeeType().getTypePtr();
+ continue;
+ }
- // -- If T is a pointer to a member function of a class X, its
- // associated namespaces and classes are those associated
- // with the function parameter types and return type,
- // together with those associated with X.
- //
- // -- If T is a pointer to a data member of class X, its
- // associated namespaces and classes are those associated
- // with the member type together with those associated with
- // X.
- if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) {
- // Handle the type that the pointer to member points to.
- addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
- Context,
- AssociatedNamespaces,
- AssociatedClasses);
-
- // Handle the class type into which this points.
- if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>())
- addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
- Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ // As an extension, treat this like a normal pointer.
+ case Type::BlockPointer:
+ T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr();
+ continue;
- return;
- }
+ // References aren't covered by the standard, but that's such an
+ // obvious defect that we cover them anyway.
+ case Type::LValueReference:
+ case Type::RValueReference:
+ T = cast<ReferenceType>(T)->getPointeeType().getTypePtr();
+ continue;
+
+ // These are fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ break;
- // FIXME: What about block pointers?
- // FIXME: What about Objective-C message sends?
+ // These are ignored by ADL.
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ break;
+ }
+
+ if (Queue.empty()) break;
+ T = Queue.back();
+ Queue.pop_back();
+ }
}
/// \brief Find the associated classes and namespaces for
More information about the cfe-commits
mailing list