jklaehn created this revision.
jklaehn added a project: clang.

Previously, `VisitAttributes` was not called for function and class templates 
and thus their attributes were not accessible using libclang.


https://reviews.llvm.org/D36955

Files:
  bindings/python/tests/cindex/test_cursor.py
  tools/libclang/CIndex.cpp


Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -907,16 +907,18 @@
   if (VisitTemplateParameters(D->getTemplateParameters()))
     return true;
   
-  return VisitFunctionDecl(D->getTemplatedDecl());
+  auto* FD = D->getTemplatedDecl();
+  return VisitAttributes(FD) || VisitFunctionDecl(FD);
 }
 
 bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   // FIXME: Visit the "outer" template parameter lists on the TagDecl
   // before visiting these template parameters.
   if (VisitTemplateParameters(D->getTemplateParameters()))
     return true;
   
-  return VisitCXXRecordDecl(D->getTemplatedDecl());
+  auto* CD = D->getTemplatedDecl();
+  return VisitAttributes(CD) || VisitCXXRecordDecl(CD);
 }
 
 bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) 
{
Index: bindings/python/tests/cindex/test_cursor.py
===================================================================
--- bindings/python/tests/cindex/test_cursor.py
+++ bindings/python/tests/cindex/test_cursor.py
@@ -377,6 +377,26 @@
     else:
         assert False, "Couldn't find annotation"
 
+def test_annotation_template():
+    annotation = '__attribute__ ((annotate("annotation")))'
+    for source, kind in [
+            ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE),
+            ('class %s foo {};', CursorKind.CLASS_TEMPLATE),
+    ]:
+        source = 'template<typename T> ' + (source % annotation)
+        tu = get_tu(source, lang="cpp")
+
+        foo = get_cursor(tu, 'foo')
+        assert foo is not None
+        assert foo.kind == kind
+
+        for c in foo.get_children():
+            if c.kind == CursorKind.ANNOTATE_ATTR:
+                assert c.displayname == "annotation"
+                break
+        else:
+            assert False, "Couldn't find annotation for {}".format(kind)
+
 def test_result_type():
     tu = get_tu('int foo();')
     foo = get_cursor(tu, 'foo')


Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -907,16 +907,18 @@
   if (VisitTemplateParameters(D->getTemplateParameters()))
     return true;
   
-  return VisitFunctionDecl(D->getTemplatedDecl());
+  auto* FD = D->getTemplatedDecl();
+  return VisitAttributes(FD) || VisitFunctionDecl(FD);
 }
 
 bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   // FIXME: Visit the "outer" template parameter lists on the TagDecl
   // before visiting these template parameters.
   if (VisitTemplateParameters(D->getTemplateParameters()))
     return true;
   
-  return VisitCXXRecordDecl(D->getTemplatedDecl());
+  auto* CD = D->getTemplatedDecl();
+  return VisitAttributes(CD) || VisitCXXRecordDecl(CD);
 }
 
 bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
Index: bindings/python/tests/cindex/test_cursor.py
===================================================================
--- bindings/python/tests/cindex/test_cursor.py
+++ bindings/python/tests/cindex/test_cursor.py
@@ -377,6 +377,26 @@
     else:
         assert False, "Couldn't find annotation"
 
+def test_annotation_template():
+    annotation = '__attribute__ ((annotate("annotation")))'
+    for source, kind in [
+            ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE),
+            ('class %s foo {};', CursorKind.CLASS_TEMPLATE),
+    ]:
+        source = 'template<typename T> ' + (source % annotation)
+        tu = get_tu(source, lang="cpp")
+
+        foo = get_cursor(tu, 'foo')
+        assert foo is not None
+        assert foo.kind == kind
+
+        for c in foo.get_children():
+            if c.kind == CursorKind.ANNOTATE_ATTR:
+                assert c.displayname == "annotation"
+                break
+        else:
+            assert False, "Couldn't find annotation for {}".format(kind)
+
 def test_result_type():
     tu = get_tu('int foo();')
     foo = get_cursor(tu, 'foo')
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to