Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h	(revision 111934)
+++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -123,12 +123,26 @@
 /// users may override Traverse* and WalkUpFrom* to implement custom
 /// traversal strategies.  Returning false from one of these overridden
 /// functions will abort the entire traversal.
+///
+/// This visitor always recurses in the declarator of explicit
+/// template instantiations, such as for example "template class
+/// set<int>'. But by default, it will not recurse in the
+/// instantiations (implicit or explicit) of the template (function or
+/// class) themselves since the instatiated AST isn't written in the
+/// source code anywhere. This behavior can be changed by overriding
+/// shouldVisitTemplateInstantiations() in the derived class to return
+/// true.
+
 template<typename Derived>
 class RecursiveASTVisitor {
 public:
   /// \brief Return a reference to the derived class.
   Derived &getDerived() { return *static_cast<Derived*>(this); }
 
+  /// \brief Return whether this visitor should recurse into
+  /// template instantiations.
+  bool shouldVisitTemplateInstantiations() const { return false; }
+  
   /// \brief Recursively visit a statement or expression, by
   /// dispatching to Traverse*() based on the argument's dynamic type.
   ///
@@ -351,7 +365,9 @@
 private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
-  bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+  bool TraverseImplicitClassInstantiations(ClassTemplateDecl* D);
+  bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
+  bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, 
                                           unsigned Count);
   bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
   bool TraverseRecordHelper(RecordDecl *D);
@@ -1092,19 +1108,96 @@
   return true;
 }
 
+// A helper method for traversing the implicit instantiations of a
+// class.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseImplicitClassInstantiations(
+  ClassTemplateDecl* D) {
+  // By default, we do not traverse the instantiations of
+  // class templates since they do not apprear in the user code. The
+  // following code optionally traverses them.
+  if (!getDerived().shouldVisitTemplateInstantiations())
+    return true;
+  
+  ClassTemplateDecl::spec_iterator end = D->spec_end();
+  for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+    ClassTemplateSpecializationDecl* SD = *it;
+
+    switch (SD->getSpecializationKind()) {
+    case TSK_Undeclared:
+      assert(false && "Semantically correct ASTs cannot contain "
+             "undeclared specializations.");
+    case TSK_ImplicitInstantiation: 
+      TRY_TO(TraverseClassTemplateSpecializationDecl(*it));
+      break;
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+    case TSK_ExplicitSpecialization:
+      break;
+    default:
+      assert(false && "Unknown specialization kind.");
+    }
+  }
+
+  return true;
+}
+  
 DEF_TRAVERSE_DECL(ClassTemplateDecl, {
     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-    // We should not traverse the specializations/partial
-    // specializations.  Those will show up in other contexts.
-    // getInstantiatedFromMemberTemplate() is just a link from a
-    // template instantiation back to the template from which it was
-    // instantiated, and thus should not be traversed either.
+    // Explicit class intantiations and specializations will be
+    // traversed from the context of their declaration. There
+    // is therefore no need to traverse them for here.
+    TRY_TO(TraverseImplicitClassInstantiations(D));
+
+    // Partial specializations are already traversed from their
+    // definition context. There is therefore no need to traverse them
+    // from here.
+    
+    // Note that getInstantiatedFromMemberTemplate() is just a link
+    // from a template instantiation back to the template from which
+    // it was instantiated, and thus should not be traversed.
   })
 
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+  FunctionTemplateDecl* D) {
+  // By default, we do not traverse the instantiations of
+  // function templates since they do not apprear in the user code. The
+  // following code optionally traverses them.
+  if (!getDerived().shouldVisitTemplateInstantiations())
+    return true;
+  
+  FunctionTemplateDecl::spec_iterator end = D->spec_end();
+  for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+    FunctionDecl* FD = *it;
+    switch (FD->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:           // Declaration of the template definition.
+    case TSK_ImplicitInstantiation: 
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      TRY_TO(TraverseFunctionDecl(*it));
+      break;
+
+    case TSK_ExplicitSpecialization:
+      break;
+    default:
+      assert(false && "Unknown specialization kind.");
+    }
+  }
+  
+  return true;
+}
+  
 DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+    // Explicit function specializations will be traversed from the
+    // context of their declaration. There is therefore no need to
+    // traverse them for here.
+    TRY_TO(TraverseFunctionInstantiations(D));
   })
 
 DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
@@ -1192,18 +1285,22 @@
   })
 
 DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
-    // For implicit instantiations ("set<int> x;"), we don't want to
-    // recurse at all, since the instatiated class isn't written in
-    // the source code anywhere.  (Note the instatiated *type* --
-    // set<int> -- is written, and will still get a callback of
-    // TemplateSpecializationType).  For explicit instantiations
-    // ("template set<int>;"), we do need a callback, since this
-    // is the only callback that's made for this instantiation.
-    // We use getTypeAsWritten() to distinguish.
-    // FIXME: see how we want to handle template specializations.
-    if (TypeSourceInfo *TSI = D->getTypeAsWritten())
-      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-    return true;
+    if (shouldVisitTemplateInstantiations()) {
+      TRY_TO(TraverseCXXRecordHelper(D));
+    }
+    else {
+      // For implicit instantiations ("set<int> x;"), we don't want to
+      // recurse at all, since the instatiated class isn't written in
+      // the source code anywhere.  (Note the instatiated *type* --
+      // set<int> -- is written, and will still get a callback of
+      // TemplateSpecializationType).  For explicit instantiations
+      // ("template set<int>;"), we do need a callback, since this
+      // is the only callback that's made for this instantiation.
+      // We use getTypeAsWritten() to distinguish.
+      // FIXME: see how we want to handle template specializations.
+      if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+        TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+    }
   })
 
 template <typename Derived>
