CXType.cpp revision 84b796492de8a708150dd3f86ae191041d42eef9
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 TKCASE(ConstantArray); 88 TKCASE(Vector); 89 default: 90 return CXType_Unexposed; 91 } 92#undef TKCASE 93} 94 95 96CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { 97 CXTypeKind TK = GetTypeKind(T); 98 CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; 99 return CT; 100} 101 102using cxtype::MakeCXType; 103 104static inline QualType GetQualType(CXType CT) { 105 return QualType::getFromOpaquePtr(CT.data[0]); 106} 107 108static inline CXTranslationUnit GetTU(CXType CT) { 109 return static_cast<CXTranslationUnit>(CT.data[1]); 110} 111 112extern "C" { 113 114CXType clang_getCursorType(CXCursor C) { 115 using namespace cxcursor; 116 117 CXTranslationUnit TU = cxcursor::getCursorTU(C); 118 ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext(); 119 if (clang_isExpression(C.kind)) { 120 QualType T = cxcursor::getCursorExpr(C)->getType(); 121 return MakeCXType(T, TU); 122 } 123 124 if (clang_isDeclaration(C.kind)) { 125 Decl *D = cxcursor::getCursorDecl(C); 126 127 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 128 return MakeCXType(Context.getTypeDeclType(TD), TU); 129 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 130 return MakeCXType(Context.getObjCInterfaceType(ID), TU); 131 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 132 return MakeCXType(VD->getType(), TU); 133 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) 134 return MakeCXType(PD->getType(), TU); 135 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 136 return MakeCXType(FD->getType(), TU); 137 return MakeCXType(QualType(), TU); 138 } 139 140 if (clang_isReference(C.kind)) { 141 switch (C.kind) { 142 case CXCursor_ObjCSuperClassRef: { 143 QualType T 144 = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first); 145 return MakeCXType(T, TU); 146 } 147 148 case CXCursor_ObjCClassRef: { 149 QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first); 150 return MakeCXType(T, TU); 151 } 152 153 case CXCursor_TypeRef: { 154 QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first); 155 return MakeCXType(T, TU); 156 157 } 158 159 case CXCursor_CXXBaseSpecifier: 160 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU); 161 162 case CXCursor_ObjCProtocolRef: 163 case CXCursor_TemplateRef: 164 case CXCursor_NamespaceRef: 165 case CXCursor_MemberRef: 166 case CXCursor_OverloadedDeclRef: 167 default: 168 break; 169 } 170 171 return MakeCXType(QualType(), TU); 172 } 173 174 return MakeCXType(QualType(), TU); 175} 176 177CXType clang_getTypedefDeclUnderlyingType(CXCursor C) { 178 using namespace cxcursor; 179 CXTranslationUnit TU = cxcursor::getCursorTU(C); 180 181 if (clang_isDeclaration(C.kind)) { 182 Decl *D = cxcursor::getCursorDecl(C); 183 184 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 185 QualType T = TD->getUnderlyingType(); 186 return MakeCXType(T, TU); 187 } 188 189 return MakeCXType(QualType(), TU); 190 } 191 192 return MakeCXType(QualType(), TU); 193} 194 195CXType clang_getEnumDeclIntegerType(CXCursor C) { 196 using namespace cxcursor; 197 CXTranslationUnit TU = cxcursor::getCursorTU(C); 198 199 if (clang_isDeclaration(C.kind)) { 200 Decl *D = cxcursor::getCursorDecl(C); 201 202 if (EnumDecl *TD = dyn_cast<EnumDecl>(D)) { 203 QualType T = TD->getIntegerType(); 204 return MakeCXType(T, TU); 205 } 206 207 return MakeCXType(QualType(), TU); 208 } 209 210 return MakeCXType(QualType(), TU); 211} 212 213long long clang_getEnumConstantDeclValue(CXCursor C) { 214 using namespace cxcursor; 215 216 if (clang_isDeclaration(C.kind)) { 217 Decl *D = cxcursor::getCursorDecl(C); 218 219 if (EnumConstantDecl *TD = dyn_cast<EnumConstantDecl>(D)) { 220 return TD->getInitVal().getSExtValue(); 221 } 222 223 return LLONG_MIN; 224 } 225 226 return LLONG_MIN; 227} 228 229unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) { 230 using namespace cxcursor; 231 232 if (clang_isDeclaration(C.kind)) { 233 Decl *D = cxcursor::getCursorDecl(C); 234 235 if (EnumConstantDecl *TD = dyn_cast<EnumConstantDecl>(D)) { 236 return TD->getInitVal().getZExtValue(); 237 } 238 239 return ULLONG_MAX; 240 } 241 242 return ULLONG_MAX; 243} 244 245CXType clang_getCanonicalType(CXType CT) { 246 if (CT.kind == CXType_Invalid) 247 return CT; 248 249 QualType T = GetQualType(CT); 250 CXTranslationUnit TU = GetTU(CT); 251 252 if (T.isNull()) 253 return MakeCXType(QualType(), GetTU(CT)); 254 255 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 256 return MakeCXType(AU->getASTContext().getCanonicalType(T), TU); 257} 258 259unsigned clang_isConstQualifiedType(CXType CT) { 260 QualType T = GetQualType(CT); 261 return T.isLocalConstQualified(); 262} 263 264unsigned clang_isVolatileQualifiedType(CXType CT) { 265 QualType T = GetQualType(CT); 266 return T.isLocalVolatileQualified(); 267} 268 269unsigned clang_isRestrictQualifiedType(CXType CT) { 270 QualType T = GetQualType(CT); 271 return T.isLocalRestrictQualified(); 272} 273 274CXType clang_getPointeeType(CXType CT) { 275 QualType T = GetQualType(CT); 276 const Type *TP = T.getTypePtrOrNull(); 277 278 if (!TP) 279 return MakeCXType(QualType(), GetTU(CT)); 280 281 switch (TP->getTypeClass()) { 282 case Type::Pointer: 283 T = cast<PointerType>(TP)->getPointeeType(); 284 break; 285 case Type::BlockPointer: 286 T = cast<BlockPointerType>(TP)->getPointeeType(); 287 break; 288 case Type::LValueReference: 289 case Type::RValueReference: 290 T = cast<ReferenceType>(TP)->getPointeeType(); 291 break; 292 case Type::ObjCObjectPointer: 293 T = cast<ObjCObjectPointerType>(TP)->getPointeeType(); 294 break; 295 default: 296 T = QualType(); 297 break; 298 } 299 return MakeCXType(T, GetTU(CT)); 300} 301 302CXCursor clang_getTypeDeclaration(CXType CT) { 303 if (CT.kind == CXType_Invalid) 304 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 305 306 QualType T = GetQualType(CT); 307 const Type *TP = T.getTypePtrOrNull(); 308 309 if (!TP) 310 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 311 312 Decl *D = 0; 313 314try_again: 315 switch (TP->getTypeClass()) { 316 case Type::Typedef: 317 D = cast<TypedefType>(TP)->getDecl(); 318 break; 319 case Type::ObjCObject: 320 D = cast<ObjCObjectType>(TP)->getInterface(); 321 break; 322 case Type::ObjCInterface: 323 D = cast<ObjCInterfaceType>(TP)->getDecl(); 324 break; 325 case Type::Record: 326 case Type::Enum: 327 D = cast<TagType>(TP)->getDecl(); 328 break; 329 case Type::TemplateSpecialization: 330 if (const RecordType *Record = TP->getAs<RecordType>()) 331 D = Record->getDecl(); 332 else 333 D = cast<TemplateSpecializationType>(TP)->getTemplateName() 334 .getAsTemplateDecl(); 335 break; 336 337 case Type::InjectedClassName: 338 D = cast<InjectedClassNameType>(TP)->getDecl(); 339 break; 340 341 // FIXME: Template type parameters! 342 343 case Type::Elaborated: 344 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull(); 345 goto try_again; 346 347 default: 348 break; 349 } 350 351 if (!D) 352 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 353 354 return cxcursor::MakeCXCursor(D, GetTU(CT)); 355} 356 357CXString clang_getTypeKindSpelling(enum CXTypeKind K) { 358 const char *s = 0; 359#define TKIND(X) case CXType_##X: s = "" #X ""; break 360 switch (K) { 361 TKIND(Invalid); 362 TKIND(Unexposed); 363 TKIND(Void); 364 TKIND(Bool); 365 TKIND(Char_U); 366 TKIND(UChar); 367 TKIND(Char16); 368 TKIND(Char32); 369 TKIND(UShort); 370 TKIND(UInt); 371 TKIND(ULong); 372 TKIND(ULongLong); 373 TKIND(UInt128); 374 TKIND(Char_S); 375 TKIND(SChar); 376 case CXType_WChar: s = "WChar"; break; 377 TKIND(Short); 378 TKIND(Int); 379 TKIND(Long); 380 TKIND(LongLong); 381 TKIND(Int128); 382 TKIND(Float); 383 TKIND(Double); 384 TKIND(LongDouble); 385 TKIND(NullPtr); 386 TKIND(Overload); 387 TKIND(Dependent); 388 TKIND(ObjCId); 389 TKIND(ObjCClass); 390 TKIND(ObjCSel); 391 TKIND(Complex); 392 TKIND(Pointer); 393 TKIND(BlockPointer); 394 TKIND(LValueReference); 395 TKIND(RValueReference); 396 TKIND(Record); 397 TKIND(Enum); 398 TKIND(Typedef); 399 TKIND(ObjCInterface); 400 TKIND(ObjCObjectPointer); 401 TKIND(FunctionNoProto); 402 TKIND(FunctionProto); 403 TKIND(ConstantArray); 404 TKIND(Vector); 405 } 406#undef TKIND 407 return cxstring::createCXString(s); 408} 409 410unsigned clang_equalTypes(CXType A, CXType B) { 411 return A.data[0] == B.data[0] && A.data[1] == B.data[1];; 412} 413 414unsigned clang_isFunctionTypeVariadic(CXType X) { 415 QualType T = GetQualType(X); 416 if (T.isNull()) 417 return 0; 418 419 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) 420 return (unsigned)FD->isVariadic(); 421 422 if (T->getAs<FunctionNoProtoType>()) 423 return 1; 424 425 return 0; 426} 427 428CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { 429 QualType T = GetQualType(X); 430 if (T.isNull()) 431 return CXCallingConv_Invalid; 432 433 if (const FunctionType *FD = T->getAs<FunctionType>()) { 434#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X 435 switch (FD->getCallConv()) { 436 TCALLINGCONV(Default); 437 TCALLINGCONV(C); 438 TCALLINGCONV(X86StdCall); 439 TCALLINGCONV(X86FastCall); 440 TCALLINGCONV(X86ThisCall); 441 TCALLINGCONV(X86Pascal); 442 TCALLINGCONV(AAPCS); 443 TCALLINGCONV(AAPCS_VFP); 444 default: 445 return CXCallingConv_Unexposed; 446 } 447#undef TCALLINGCONV 448 } 449 450 return CXCallingConv_Invalid; 451} 452 453unsigned clang_getNumArgTypes(CXType X) { 454 QualType T = GetQualType(X); 455 if (T.isNull()) 456 return UINT_MAX; 457 458 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) { 459 return FD->getNumArgs(); 460 } 461 462 if (T->getAs<FunctionNoProtoType>()) { 463 return 0; 464 } 465 466 return UINT_MAX; 467} 468 469CXType clang_getArgType(CXType X, unsigned i) { 470 QualType T = GetQualType(X); 471 if (T.isNull()) 472 return MakeCXType(QualType(), GetTU(X)); 473 474 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) { 475 unsigned numArgs = FD->getNumArgs(); 476 if (i >= numArgs) 477 return MakeCXType(QualType(), GetTU(X)); 478 479 return MakeCXType(FD->getArgType(i), GetTU(X)); 480 } 481 482 return MakeCXType(QualType(), GetTU(X)); 483} 484 485CXType clang_getResultType(CXType X) { 486 QualType T = GetQualType(X); 487 if (T.isNull()) 488 return MakeCXType(QualType(), GetTU(X)); 489 490 if (const FunctionType *FD = T->getAs<FunctionType>()) 491 return MakeCXType(FD->getResultType(), GetTU(X)); 492 493 return MakeCXType(QualType(), GetTU(X)); 494} 495 496CXType clang_getCursorResultType(CXCursor C) { 497 if (clang_isDeclaration(C.kind)) { 498 Decl *D = cxcursor::getCursorDecl(C); 499 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 500 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C)); 501 502 return clang_getResultType(clang_getCursorType(C)); 503 } 504 505 return MakeCXType(QualType(), cxcursor::getCursorTU(C)); 506} 507 508unsigned clang_isPODType(CXType X) { 509 QualType T = GetQualType(X); 510 if (T.isNull()) 511 return 0; 512 513 CXTranslationUnit TU = GetTU(X); 514 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 515 516 return T.isPODType(AU->getASTContext()) ? 1 : 0; 517} 518 519CXType clang_getElementType(CXType CT) { 520 QualType ET = QualType(); 521 QualType T = GetQualType(CT); 522 const Type *TP = T.getTypePtrOrNull(); 523 524 if (TP) { 525 switch (TP->getTypeClass()) { 526 case Type::ConstantArray: 527 ET = cast<ConstantArrayType> (TP)->getElementType(); 528 break; 529 case Type::Vector: 530 ET = cast<VectorType> (TP)->getElementType(); 531 break; 532 case Type::Complex: 533 ET = cast<ComplexType> (TP)->getElementType(); 534 break; 535 default: 536 break; 537 } 538 } 539 return MakeCXType(ET, GetTU(CT)); 540} 541 542long long clang_getNumElements(CXType CT) { 543 long long result = -1; 544 QualType T = GetQualType(CT); 545 const Type *TP = T.getTypePtrOrNull(); 546 547 if (TP) { 548 switch (TP->getTypeClass()) { 549 case Type::ConstantArray: 550 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue(); 551 break; 552 case Type::Vector: 553 result = cast<VectorType> (TP)->getNumElements(); 554 break; 555 default: 556 break; 557 } 558 } 559 return result; 560} 561 562CXType clang_getArrayElementType(CXType CT) { 563 QualType ET = QualType(); 564 QualType T = GetQualType(CT); 565 const Type *TP = T.getTypePtrOrNull(); 566 567 if (TP) { 568 switch (TP->getTypeClass()) { 569 case Type::ConstantArray: 570 ET = cast<ConstantArrayType> (TP)->getElementType(); 571 break; 572 default: 573 break; 574 } 575 } 576 return MakeCXType(ET, GetTU(CT)); 577} 578 579long long clang_getArraySize(CXType CT) { 580 long long result = -1; 581 QualType T = GetQualType(CT); 582 const Type *TP = T.getTypePtrOrNull(); 583 584 if (TP) { 585 switch (TP->getTypeClass()) { 586 case Type::ConstantArray: 587 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue(); 588 break; 589 default: 590 break; 591 } 592 } 593 return result; 594} 595 596CXString clang_getDeclObjCTypeEncoding(CXCursor C) { 597 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) 598 return cxstring::createCXString(""); 599 600 Decl *D = static_cast<Decl*>(C.data[0]); 601 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]); 602 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 603 ASTContext &Ctx = AU->getASTContext(); 604 std::string encoding; 605 606 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { 607 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding)) 608 return cxstring::createCXString("?"); 609 } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) 610 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); 611 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 612 Ctx.getObjCEncodingForFunctionDecl(FD, encoding); 613 else { 614 QualType Ty; 615 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 616 Ty = Ctx.getTypeDeclType(TD); 617 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 618 Ty = VD->getType(); 619 else return cxstring::createCXString("?"); 620 Ctx.getObjCEncodingForType(Ty, encoding); 621 } 622 623 return cxstring::createCXString(encoding); 624} 625 626} // end: extern "C" 627