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 26 using namespace clang; 27 28 static 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 66 static 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 94 CXType 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 100 using cxtype::MakeCXType; 101 102 static inline QualType GetQualType(CXType CT) { 103 return QualType::getFromOpaquePtr(CT.data[0]); 104 } 105 106 static inline CXTranslationUnit GetTU(CXType CT) { 107 return static_cast<CXTranslationUnit>(CT.data[1]); 108 } 109 110 extern "C" { 111 112 CXType 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 175 CXType 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 189 unsigned clang_isConstQualifiedType(CXType CT) { 190 QualType T = GetQualType(CT); 191 return T.isLocalConstQualified(); 192 } 193 194 unsigned clang_isVolatileQualifiedType(CXType CT) { 195 QualType T = GetQualType(CT); 196 return T.isLocalVolatileQualified(); 197 } 198 199 unsigned clang_isRestrictQualifiedType(CXType CT) { 200 QualType T = GetQualType(CT); 201 return T.isLocalRestrictQualified(); 202 } 203 204 CXType clang_getPointeeType(CXType CT) { 205 QualType T = GetQualType(CT); 206 const Type *TP = T.getTypePtrOrNull(); 207 208 if (!TP) 209 return MakeCXType(QualType(), GetTU(CT)); 210 211 switch (TP->getTypeClass()) { 212 case Type::Pointer: 213 T = cast<PointerType>(TP)->getPointeeType(); 214 break; 215 case Type::BlockPointer: 216 T = cast<BlockPointerType>(TP)->getPointeeType(); 217 break; 218 case Type::LValueReference: 219 case Type::RValueReference: 220 T = cast<ReferenceType>(TP)->getPointeeType(); 221 break; 222 case Type::ObjCObjectPointer: 223 T = cast<ObjCObjectPointerType>(TP)->getPointeeType(); 224 break; 225 default: 226 T = QualType(); 227 break; 228 } 229 return MakeCXType(T, GetTU(CT)); 230 } 231 232 CXCursor clang_getTypeDeclaration(CXType CT) { 233 if (CT.kind == CXType_Invalid) 234 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 235 236 QualType T = GetQualType(CT); 237 const Type *TP = T.getTypePtrOrNull(); 238 239 if (!TP) 240 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 241 242 Decl *D = 0; 243 244 try_again: 245 switch (TP->getTypeClass()) { 246 case Type::Typedef: 247 D = cast<TypedefType>(TP)->getDecl(); 248 break; 249 case Type::ObjCObject: 250 D = cast<ObjCObjectType>(TP)->getInterface(); 251 break; 252 case Type::ObjCInterface: 253 D = cast<ObjCInterfaceType>(TP)->getDecl(); 254 break; 255 case Type::Record: 256 case Type::Enum: 257 D = cast<TagType>(TP)->getDecl(); 258 break; 259 case Type::TemplateSpecialization: 260 if (const RecordType *Record = TP->getAs<RecordType>()) 261 D = Record->getDecl(); 262 else 263 D = cast<TemplateSpecializationType>(TP)->getTemplateName() 264 .getAsTemplateDecl(); 265 break; 266 267 case Type::InjectedClassName: 268 D = cast<InjectedClassNameType>(TP)->getDecl(); 269 break; 270 271 // FIXME: Template type parameters! 272 273 case Type::Elaborated: 274 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull(); 275 goto try_again; 276 277 default: 278 break; 279 } 280 281 if (!D) 282 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 283 284 return cxcursor::MakeCXCursor(D, GetTU(CT)); 285 } 286 287 CXString clang_getTypeKindSpelling(enum CXTypeKind K) { 288 const char *s = 0; 289 #define TKIND(X) case CXType_##X: s = "" #X ""; break 290 switch (K) { 291 TKIND(Invalid); 292 TKIND(Unexposed); 293 TKIND(Void); 294 TKIND(Bool); 295 TKIND(Char_U); 296 TKIND(UChar); 297 TKIND(Char16); 298 TKIND(Char32); 299 TKIND(UShort); 300 TKIND(UInt); 301 TKIND(ULong); 302 TKIND(ULongLong); 303 TKIND(UInt128); 304 TKIND(Char_S); 305 TKIND(SChar); 306 case CXType_WChar: s = "WChar"; break; 307 TKIND(Short); 308 TKIND(Int); 309 TKIND(Long); 310 TKIND(LongLong); 311 TKIND(Int128); 312 TKIND(Float); 313 TKIND(Double); 314 TKIND(LongDouble); 315 TKIND(NullPtr); 316 TKIND(Overload); 317 TKIND(Dependent); 318 TKIND(ObjCId); 319 TKIND(ObjCClass); 320 TKIND(ObjCSel); 321 TKIND(Complex); 322 TKIND(Pointer); 323 TKIND(BlockPointer); 324 TKIND(LValueReference); 325 TKIND(RValueReference); 326 TKIND(Record); 327 TKIND(Enum); 328 TKIND(Typedef); 329 TKIND(ObjCInterface); 330 TKIND(ObjCObjectPointer); 331 TKIND(FunctionNoProto); 332 TKIND(FunctionProto); 333 } 334 #undef TKIND 335 return cxstring::createCXString(s); 336 } 337 338 unsigned clang_equalTypes(CXType A, CXType B) { 339 return A.data[0] == B.data[0] && A.data[1] == B.data[1];; 340 } 341 342 CXType clang_getResultType(CXType X) { 343 QualType T = GetQualType(X); 344 if (!T.getTypePtrOrNull()) 345 return MakeCXType(QualType(), GetTU(X)); 346 347 if (const FunctionType *FD = T->getAs<FunctionType>()) 348 return MakeCXType(FD->getResultType(), GetTU(X)); 349 350 return MakeCXType(QualType(), GetTU(X)); 351 } 352 353 CXType clang_getCursorResultType(CXCursor C) { 354 if (clang_isDeclaration(C.kind)) { 355 Decl *D = cxcursor::getCursorDecl(C); 356 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 357 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C)); 358 359 return clang_getResultType(clang_getCursorType(C)); 360 } 361 362 return MakeCXType(QualType(), cxcursor::getCursorTU(C)); 363 } 364 365 unsigned clang_isPODType(CXType X) { 366 QualType T = GetQualType(X); 367 if (!T.getTypePtrOrNull()) 368 return 0; 369 370 CXTranslationUnit TU = GetTU(X); 371 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 372 373 return T.isPODType(AU->getASTContext()) ? 1 : 0; 374 } 375 376 CXString clang_getDeclObjCTypeEncoding(CXCursor C) { 377 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) 378 return cxstring::createCXString(""); 379 380 Decl *D = static_cast<Decl*>(C.data[0]); 381 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]); 382 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 383 ASTContext &Ctx = AU->getASTContext(); 384 std::string encoding; 385 386 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { 387 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding)) 388 return cxstring::createCXString("?"); 389 } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) 390 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); 391 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 392 Ctx.getObjCEncodingForFunctionDecl(FD, encoding); 393 else { 394 QualType Ty; 395 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 396 Ty = Ctx.getTypeDeclType(TD); 397 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 398 Ty = VD->getType(); 399 else return cxstring::createCXString("?"); 400 Ctx.getObjCEncodingForType(Ty, encoding); 401 } 402 403 return cxstring::createCXString(encoding); 404 } 405 406 } // end: extern "C" 407