CXType.cpp revision fbcfeeabed6aa60ba664be302f2b03bed3d1b24d
1//===- CXTypes.cpp - Implements 'CXTypes' aspect of libclang ------------===// 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 'CXTypes' API hooks in the Clang-C library. 11// 12//===--------------------------------------------------------------------===// 13 14#include "CIndexer.h" 15#include "CXTranslationUnit.h" 16#include "CXCursor.h" 17#include "CXString.h" 18#include "CXType.h" 19#include "clang/AST/Expr.h" 20#include "clang/AST/Type.h" 21#include "clang/AST/Decl.h" 22#include "clang/AST/DeclObjC.h" 23#include "clang/AST/DeclTemplate.h" 24#include "clang/Frontend/ASTUnit.h" 25 26using namespace clang; 27 28static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) { 29#define BTCASE(K) case BuiltinType::K: return CXType_##K 30 switch (BT->getKind()) { 31 BTCASE(Void); 32 BTCASE(Bool); 33 BTCASE(Char_U); 34 BTCASE(UChar); 35 BTCASE(Char16); 36 BTCASE(Char32); 37 BTCASE(UShort); 38 BTCASE(UInt); 39 BTCASE(ULong); 40 BTCASE(ULongLong); 41 BTCASE(UInt128); 42 BTCASE(Char_S); 43 BTCASE(SChar); 44 case BuiltinType::WChar_S: return CXType_WChar; 45 case BuiltinType::WChar_U: return CXType_WChar; 46 BTCASE(Short); 47 BTCASE(Int); 48 BTCASE(Long); 49 BTCASE(LongLong); 50 BTCASE(Int128); 51 BTCASE(Float); 52 BTCASE(Double); 53 BTCASE(LongDouble); 54 BTCASE(NullPtr); 55 BTCASE(Overload); 56 BTCASE(Dependent); 57 BTCASE(ObjCId); 58 BTCASE(ObjCClass); 59 BTCASE(ObjCSel); 60 default: 61 return CXType_Unexposed; 62 } 63#undef BTCASE 64} 65 66static CXTypeKind GetTypeKind(QualType T) { 67 const Type *TP = T.getTypePtrOrNull(); 68 if (!TP) 69 return CXType_Invalid; 70 71#define TKCASE(K) case Type::K: return CXType_##K 72 switch (TP->getTypeClass()) { 73 case Type::Builtin: 74 return GetBuiltinTypeKind(cast<BuiltinType>(TP)); 75 TKCASE(Complex); 76 TKCASE(Pointer); 77 TKCASE(BlockPointer); 78 TKCASE(LValueReference); 79 TKCASE(RValueReference); 80 TKCASE(Record); 81 TKCASE(Enum); 82 TKCASE(Typedef); 83 TKCASE(ObjCInterface); 84 TKCASE(ObjCObjectPointer); 85 TKCASE(FunctionNoProto); 86 TKCASE(FunctionProto); 87 default: 88 return CXType_Unexposed; 89 } 90#undef TKCASE 91} 92 93 94CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { 95 CXTypeKind TK = GetTypeKind(T); 96 CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; 97 return CT; 98} 99 100using cxtype::MakeCXType; 101 102static inline QualType GetQualType(CXType CT) { 103 return QualType::getFromOpaquePtr(CT.data[0]); 104} 105 106static inline CXTranslationUnit GetTU(CXType CT) { 107 return static_cast<CXTranslationUnit>(CT.data[1]); 108} 109 110extern "C" { 111 112CXType clang_getCursorType(CXCursor C) { 113 using namespace cxcursor; 114 115 CXTranslationUnit TU = cxcursor::getCursorTU(C); 116 ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext(); 117 if (clang_isExpression(C.kind)) { 118 QualType T = cxcursor::getCursorExpr(C)->getType(); 119 return MakeCXType(T, TU); 120 } 121 122 if (clang_isDeclaration(C.kind)) { 123 Decl *D = cxcursor::getCursorDecl(C); 124 125 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 126 return MakeCXType(Context.getTypeDeclType(TD), TU); 127 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 128 return MakeCXType(Context.getObjCInterfaceType(ID), TU); 129 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 130 return MakeCXType(VD->getType(), TU); 131 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) 132 return MakeCXType(PD->getType(), TU); 133 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 134 return MakeCXType(FD->getType(), TU); 135 return MakeCXType(QualType(), TU); 136 } 137 138 if (clang_isReference(C.kind)) { 139 switch (C.kind) { 140 case CXCursor_ObjCSuperClassRef: { 141 QualType T 142 = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first); 143 return MakeCXType(T, TU); 144 } 145 146 case CXCursor_ObjCClassRef: { 147 QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first); 148 return MakeCXType(T, TU); 149 } 150 151 case CXCursor_TypeRef: { 152 QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first); 153 return MakeCXType(T, TU); 154 155 } 156 157 case CXCursor_CXXBaseSpecifier: 158 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU); 159 160 case CXCursor_ObjCProtocolRef: 161 case CXCursor_TemplateRef: 162 case CXCursor_NamespaceRef: 163 case CXCursor_MemberRef: 164 case CXCursor_OverloadedDeclRef: 165 default: 166 break; 167 } 168 169 return MakeCXType(QualType(), TU); 170 } 171 172 return MakeCXType(QualType(), TU); 173} 174 175CXType clang_getCanonicalType(CXType CT) { 176 if (CT.kind == CXType_Invalid) 177 return CT; 178 179 QualType T = GetQualType(CT); 180 CXTranslationUnit TU = GetTU(CT); 181 182 if (T.isNull()) 183 return MakeCXType(QualType(), GetTU(CT)); 184 185 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 186 return MakeCXType(AU->getASTContext().getCanonicalType(T), TU); 187} 188 189CXType clang_getPointeeType(CXType CT) { 190 QualType T = GetQualType(CT); 191 const Type *TP = T.getTypePtrOrNull(); 192 193 if (!TP) 194 return MakeCXType(QualType(), GetTU(CT)); 195 196 switch (TP->getTypeClass()) { 197 case Type::Pointer: 198 T = cast<PointerType>(TP)->getPointeeType(); 199 break; 200 case Type::BlockPointer: 201 T = cast<BlockPointerType>(TP)->getPointeeType(); 202 break; 203 case Type::LValueReference: 204 case Type::RValueReference: 205 T = cast<ReferenceType>(TP)->getPointeeType(); 206 break; 207 case Type::ObjCObjectPointer: 208 T = cast<ObjCObjectPointerType>(TP)->getPointeeType(); 209 break; 210 default: 211 T = QualType(); 212 break; 213 } 214 return MakeCXType(T, GetTU(CT)); 215} 216 217CXCursor clang_getTypeDeclaration(CXType CT) { 218 if (CT.kind == CXType_Invalid) 219 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 220 221 QualType T = GetQualType(CT); 222 const Type *TP = T.getTypePtrOrNull(); 223 224 if (!TP) 225 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 226 227 Decl *D = 0; 228 229try_again: 230 switch (TP->getTypeClass()) { 231 case Type::Typedef: 232 D = cast<TypedefType>(TP)->getDecl(); 233 break; 234 case Type::ObjCObject: 235 D = cast<ObjCObjectType>(TP)->getInterface(); 236 break; 237 case Type::ObjCInterface: 238 D = cast<ObjCInterfaceType>(TP)->getDecl(); 239 break; 240 case Type::Record: 241 case Type::Enum: 242 D = cast<TagType>(TP)->getDecl(); 243 break; 244 case Type::TemplateSpecialization: 245 if (const RecordType *Record = TP->getAs<RecordType>()) 246 D = Record->getDecl(); 247 else 248 D = cast<TemplateSpecializationType>(TP)->getTemplateName() 249 .getAsTemplateDecl(); 250 break; 251 252 case Type::InjectedClassName: 253 D = cast<InjectedClassNameType>(TP)->getDecl(); 254 break; 255 256 // FIXME: Template type parameters! 257 258 case Type::Elaborated: 259 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull(); 260 goto try_again; 261 262 default: 263 break; 264 } 265 266 if (!D) 267 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 268 269 return cxcursor::MakeCXCursor(D, GetTU(CT)); 270} 271 272CXString clang_getTypeKindSpelling(enum CXTypeKind K) { 273 const char *s = 0; 274#define TKIND(X) case CXType_##X: s = "" #X ""; break 275 switch (K) { 276 TKIND(Invalid); 277 TKIND(Unexposed); 278 TKIND(Void); 279 TKIND(Bool); 280 TKIND(Char_U); 281 TKIND(UChar); 282 TKIND(Char16); 283 TKIND(Char32); 284 TKIND(UShort); 285 TKIND(UInt); 286 TKIND(ULong); 287 TKIND(ULongLong); 288 TKIND(UInt128); 289 TKIND(Char_S); 290 TKIND(SChar); 291 case CXType_WChar: s = "WChar"; break; 292 TKIND(Short); 293 TKIND(Int); 294 TKIND(Long); 295 TKIND(LongLong); 296 TKIND(Int128); 297 TKIND(Float); 298 TKIND(Double); 299 TKIND(LongDouble); 300 TKIND(NullPtr); 301 TKIND(Overload); 302 TKIND(Dependent); 303 TKIND(ObjCId); 304 TKIND(ObjCClass); 305 TKIND(ObjCSel); 306 TKIND(Complex); 307 TKIND(Pointer); 308 TKIND(BlockPointer); 309 TKIND(LValueReference); 310 TKIND(RValueReference); 311 TKIND(Record); 312 TKIND(Enum); 313 TKIND(Typedef); 314 TKIND(ObjCInterface); 315 TKIND(ObjCObjectPointer); 316 TKIND(FunctionNoProto); 317 TKIND(FunctionProto); 318 } 319#undef TKIND 320 return cxstring::createCXString(s); 321} 322 323unsigned clang_equalTypes(CXType A, CXType B) { 324 return A.data[0] == B.data[0] && A.data[1] == B.data[1];; 325} 326 327CXType clang_getResultType(CXType X) { 328 QualType T = GetQualType(X); 329 if (!T.getTypePtrOrNull()) 330 return MakeCXType(QualType(), GetTU(X)); 331 332 if (const FunctionType *FD = T->getAs<FunctionType>()) 333 return MakeCXType(FD->getResultType(), GetTU(X)); 334 335 return MakeCXType(QualType(), GetTU(X)); 336} 337 338CXType clang_getCursorResultType(CXCursor C) { 339 if (clang_isDeclaration(C.kind)) { 340 Decl *D = cxcursor::getCursorDecl(C); 341 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 342 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C)); 343 344 return clang_getResultType(clang_getCursorType(C)); 345 } 346 347 return MakeCXType(QualType(), cxcursor::getCursorTU(C)); 348} 349 350unsigned clang_isPODType(CXType X) { 351 QualType T = GetQualType(X); 352 if (!T.getTypePtrOrNull()) 353 return 0; 354 return T->isPODType() ? 1 : 0; 355} 356 357CXString clang_getDeclObjCTypeEncoding(CXCursor C) { 358 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) 359 return cxstring::createCXString(""); 360 361 Decl *D = static_cast<Decl*>(C.data[0]); 362 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]); 363 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 364 ASTContext &Ctx = AU->getASTContext(); 365 std::string encoding; 366 367 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 368 Ctx.getObjCEncodingForMethodDecl(OMD, encoding); 369 else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) 370 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); 371 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 372 Ctx.getObjCEncodingForFunctionDecl(FD, encoding); 373 else { 374 QualType Ty; 375 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 376 Ty = Ctx.getTypeDeclType(TD); 377 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 378 Ty = VD->getType(); 379 else return cxstring::createCXString("?"); 380 Ctx.getObjCEncodingForType(Ty, encoding); 381 } 382 383 return cxstring::createCXString(encoding); 384} 385 386} // end: extern "C" 387