Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h	(revision 111934)
+++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -123,12 +123,32 @@
 /// users may override Traverse* and WalkUpFrom* to implement custom
 /// traversal strategies.  Returning false from one of these overridden
 /// functions will abort the entire traversal.
+///
+/// By default this visitor will not recurse in template
+/// specializations ("set<int> x;") since the instatiated class isn't
+/// written in the source code anywhere. This behavior can be changed
+/// by calling setVisitingTemplateSpecializations(true) before
+/// starting the traversal.
 template<typename Derived>
 class RecursiveASTVisitor {
 public:
+  RecursiveASTVisitor() : visitingTemplateSpecializations(false) {}
+
   /// \brief Return a reference to the derived class.
   Derived &getDerived() { return *static_cast<Derived*>(this); }
 
+  /// \brief Control whether this visitor should recurse into
+  /// template specializations.
+  void setVisitingTemplateSpecializations(bool flag) {
+    visitingTemplateSpecializations = flag;
+  }
+  
+  /// \brief Return whether this visitor should recurse into
+  /// template specializations.
+  bool isVisitingTemplateSpecializations() const {
+    return visitingTemplateSpecializations;
+  }
+  
   /// \brief Recursively visit a statement or expression, by
   /// dispatching to Traverse*() based on the argument's dynamic type.
   ///
@@ -360,6 +380,10 @@
   bool TraverseDeclContextHelper(DeclContext *DC);
   bool TraverseFunctionHelper(FunctionDecl *D);
   bool TraverseVarHelper(VarDecl *D);
+
+  // This flag indicates that the RecursiveASTVisitor should visit
+  // template specializations.
+  bool visitingTemplateSpecializations;
 };
 
 #define DISPATCH(NAME, CLASS, VAR) \
@@ -1095,16 +1119,61 @@
 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.
+    // By default, we do not traverse the specializations/partial
+    // specializations. Implicitely instantiated templates do not
+    // apprear in the user code and explicitely instantiated templates
+    // show up in other contexts.
+    //
+    // 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.
+    //
+    // FIXME: When visiting implicitely instantiated templates, the
+    // specialization of an explicit instantiation will be visited
+    // twice, once at the template function declaration and another
+    // time at the template instantiation site. Is this an issue ? If
+    // so, when should be visited.
+    if (isVisitingTemplateSpecializations()) {
+      {
+        ClassTemplateDecl::spec_iterator end = D->spec_end();
+        for (ClassTemplateDecl::spec_iterator it = D->spec_begin();
+             it != end; ++it) {
+          TRY_TO(TraverseClassTemplateSpecializationDecl(*it));
+        }
+      }
+
+      {
+        ClassTemplateDecl::partial_spec_iterator end = D->partial_spec_end();
+        for (ClassTemplateDecl::partial_spec_iterator it = D->partial_spec_begin();
+             it != end; ++it) {
+          TRY_TO(TraverseClassTemplatePartialSpecializationDecl(*it));
+        }
+      }
+    }
   })
 
 DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+    // By default, we do not traverse the function
+    // specializations. Implicitely instantiated templates do not
+    // apprear in the user code and explicitely instantiated templates
+    // show up in other contexts.
+    //
+    // FIXME: When visiting implicitely instantiated templates, the
+    // specialization of an explicit instantiation will be visited
+    // twice, once at the template function declaration and another
+    // time at the template instantiation site. Is this an issue ? If
+    // so, when should be visited.
+    if (isVisitingTemplateSpecializations()) {
+      FunctionTemplateDecl::spec_iterator end = D->spec_end();
+      for (FunctionTemplateDecl::spec_iterator it = D->spec_begin();
+           it != end; ++it) {
+        TRY_TO(TraverseFunctionDecl(*it));
+      }
+    }
+
   })
 
 DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
@@ -1192,18 +1261,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 (isVisitingTemplateSpecializations()) {
+      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>
