blob: a992dbf12a00a31fb6c6f0556a18652e70aa2131 [file] [log] [blame]
Ted Kremenek1b6869a2010-01-05 22:06:45 +00001//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the generation and use of USRs from CXEntities.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIndexer.h"
Ted Kremenekcf84aa42010-01-18 20:23:29 +000015#include "CXCursor.h"
Benjamin Kramer9895c6a2010-01-12 11:32:40 +000016#include "clang/AST/DeclVisitor.h"
Ted Kremenek87763822010-01-12 02:07:58 +000017#include "llvm/ADT/SmallString.h"
Benjamin Kramer9895c6a2010-01-12 11:32:40 +000018#include "llvm/Support/raw_ostream.h"
Ted Kremenek1b6869a2010-01-05 22:06:45 +000019
Ted Kremenekc50277f2010-01-12 23:33:42 +000020//===----------------------------------------------------------------------===//
21// USR generation.
22//===----------------------------------------------------------------------===//
23
24namespace {
Ted Kremenek2fee4e62010-01-14 01:50:21 +000025class USRGenerator : public DeclVisitor<USRGenerator> {
26 llvm::raw_ostream &Out;
Ted Kremenek3adca6d2010-01-18 22:02:49 +000027 bool IgnoreResults;
Ted Kremenek2fee4e62010-01-14 01:50:21 +000028public:
Ted Kremenek3adca6d2010-01-18 22:02:49 +000029 USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {}
30
31 bool ignoreResults() const { return IgnoreResults; }
Ted Kremenek2fee4e62010-01-14 01:50:21 +000032
33 void VisitBlockDecl(BlockDecl *D);
34 void VisitDeclContext(DeclContext *D);
Ted Kremenek3adca6d2010-01-18 22:02:49 +000035 void VisitFieldDecl(FieldDecl *D);
Ted Kremenek2fee4e62010-01-14 01:50:21 +000036 void VisitFunctionDecl(FunctionDecl *D);
37 void VisitNamedDecl(NamedDecl *D);
38 void VisitNamespaceDecl(NamespaceDecl *D);
39 void VisitObjCContainerDecl(ObjCContainerDecl *CD);
40 void VisitObjCMethodDecl(ObjCMethodDecl *MD);
41 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
Ted Kremenekb82b3be2010-01-18 22:42:20 +000042 void VisitTagDecl(TagDecl *D);
Ted Kremenek2fee4e62010-01-14 01:50:21 +000043 void VisitTypedefDecl(TypedefDecl *D);
44};
Ted Kremenekc50277f2010-01-12 23:33:42 +000045} // end anonymous namespace
46
Ted Kremenek2fee4e62010-01-14 01:50:21 +000047void USRGenerator::VisitBlockDecl(BlockDecl *D) {
48 VisitDeclContext(D->getDeclContext());
49 // FIXME: Better support for anonymous blocks.
50 Out << "@B^anon";
51}
52
53void USRGenerator::VisitDeclContext(DeclContext *DC) {
54 if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
55 Visit(D);
56}
57
Ted Kremenek3adca6d2010-01-18 22:02:49 +000058void USRGenerator::VisitFieldDecl(FieldDecl *D) {
59 const std::string &s = D->getNameAsString();
60 if (s.empty()) {
61 // Bit fields can be anonymous.
62 IgnoreResults = true;
63 return;
64 }
65 VisitDeclContext(D->getDeclContext());
66 Out << "@^FI^" << s;
67}
68
Ted Kremenek2fee4e62010-01-14 01:50:21 +000069void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
70 VisitDeclContext(D->getDeclContext());
71 Out << "@F^" << D->getNameAsString();
72}
Ted Kremenekc50277f2010-01-12 23:33:42 +000073
74void USRGenerator::VisitNamedDecl(NamedDecl *D) {
Ted Kremenek2fee4e62010-01-14 01:50:21 +000075 VisitDeclContext(D->getDeclContext());
Ted Kremenekc50277f2010-01-12 23:33:42 +000076 const std::string &s = D->getNameAsString();
Daniel Dunbara9f696d2010-01-31 00:41:05 +000077// assert(!s.empty());
Ted Kremenek2fee4e62010-01-14 01:50:21 +000078 Out << "@^" << s;
79}
80
81void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
82 VisitDeclContext(D->getDeclContext());
83 Out << "@N^" << D->getNameAsString();
Ted Kremenekc50277f2010-01-12 23:33:42 +000084}
85
Ted Kremenekc50277f2010-01-12 23:33:42 +000086void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
87 Visit(cast<Decl>(D->getDeclContext()));
88 Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
89 Out << DeclarationName(D->getSelector()).getAsString();
90}
91
92void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
93 switch (D->getKind()) {
94 default:
95 assert(false && "Invalid ObjC container.");
96 case Decl::ObjCInterface:
97 case Decl::ObjCImplementation:
98 Out << "objc(cs)" << D->getName();
99 break;
100 case Decl::ObjCCategory: {
101 ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
102 Out << "objc(cy)" << CD->getClassInterface()->getName()
Ted Kremeneke381c992010-01-18 23:25:32 +0000103 << '^' << CD->getName();
Ted Kremenekc50277f2010-01-12 23:33:42 +0000104 break;
105 }
106 case Decl::ObjCCategoryImpl: {
107 ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
108 Out << "objc(cy)" << CD->getClassInterface()->getName()
Ted Kremeneke381c992010-01-18 23:25:32 +0000109 << '^' << CD->getName();
Ted Kremenekc50277f2010-01-12 23:33:42 +0000110 break;
111 }
112 case Decl::ObjCProtocol:
113 Out << "objc(pl)" << cast<ObjCProtocolDecl>(D)->getName();
114 break;
115 }
116}
117
118void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
119 Visit(cast<Decl>(D->getDeclContext()));
120 Out << "(py)" << D->getName();
121}
122
Ted Kremenekb82b3be2010-01-18 22:42:20 +0000123void USRGenerator::VisitTagDecl(TagDecl *D) {
124 VisitDeclContext(D->getDeclContext());
125 switch (D->getTagKind()) {
126 case TagDecl::TK_struct: Out << "@S^"; break;
127 case TagDecl::TK_class: Out << "@C^"; break;
128 case TagDecl::TK_union: Out << "@U^"; break;
129 case TagDecl::TK_enum: Out << "@E^"; break;
130 }
131
Ted Kremenekc5b48b32010-01-15 23:34:31 +0000132 // FIXME: Better support for anonymous structures and enums.
133 const std::string &s = D->getNameAsString();
134 if (s.empty()) {
135 if (TypedefDecl *TD = D->getTypedefForAnonDecl())
136 Out << "^anontd^" << TD->getNameAsString();
137 else
138 Out << "^anon";
139 }
140 else
141 Out << s;
142}
143
Ted Kremenekc50277f2010-01-12 23:33:42 +0000144void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
145 DeclContext *DC = D->getDeclContext();
146 if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
147 Visit(DCN);
148 Out << "typedef@" << D->getName();
149}
150
Ted Kremenekcf84aa42010-01-18 20:23:29 +0000151// FIXME: This is a skeleton implementation. It will be overhauled.
152static CXString ConstructUSR(Decl *D) {
153 llvm::SmallString<1024> StrBuf;
154 {
155 llvm::raw_svector_ostream Out(StrBuf);
156 USRGenerator UG(Out);
157 UG.Visit(static_cast<Decl*>(D));
Ted Kremenek3adca6d2010-01-18 22:02:49 +0000158 if (UG.ignoreResults())
159 return CIndexer::createCXString(NULL);
Ted Kremenekcf84aa42010-01-18 20:23:29 +0000160 }
161
162 if (StrBuf.empty())
163 return CIndexer::createCXString(NULL);
164
165 // Return a copy of the string that must be disposed by the caller.
166 return CIndexer::createCXString(StrBuf.c_str(), true);
167}
168
169
Benjamin Kramer9895c6a2010-01-12 11:32:40 +0000170extern "C" {
171
Ted Kremenekcf84aa42010-01-18 20:23:29 +0000172CXString clang_getCursorUSR(CXCursor C) {
173 if (Decl *D = cxcursor::getCursorDecl(C))
Ted Kremeneke381c992010-01-18 23:25:32 +0000174 return ConstructUSR(D);
Ted Kremenekcf84aa42010-01-18 20:23:29 +0000175
176 return CIndexer::createCXString(NULL);
177}
Ted Kremenek1b6869a2010-01-05 22:06:45 +0000178
Ted Kremenek1b6869a2010-01-05 22:06:45 +0000179} // end extern "C"