CXType.cpp revision f4c7371fb1d3cebcfb40abad4537bb82515704ea
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 if (clang_isExpression(C.kind)) { 117 QualType T = cxcursor::getCursorExpr(C)->getType(); 118 return MakeCXType(T, TU); 119 } 120 121 if (clang_isDeclaration(C.kind)) { 122 Decl *D = cxcursor::getCursorDecl(C); 123 124 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 125 return MakeCXType(QualType(TD->getTypeForDecl(), 0), TU); 126 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 127 return MakeCXType(QualType(ID->getTypeForDecl(), 0), TU); 128 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 129 return MakeCXType(VD->getType(), TU); 130 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) 131 return MakeCXType(PD->getType(), TU); 132 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 133 return MakeCXType(FD->getType(), TU); 134 return MakeCXType(QualType(), TU); 135 } 136 137 if (clang_isReference(C.kind)) { 138 switch (C.kind) { 139 case CXCursor_ObjCSuperClassRef: 140 return MakeCXType( 141 QualType(getCursorObjCSuperClassRef(C).first->getTypeForDecl(), 142 0), 143 TU); 144 145 case CXCursor_ObjCClassRef: 146 return MakeCXType( 147 QualType(getCursorObjCClassRef(C).first->getTypeForDecl(), 148 0), 149 TU); 150 151 case CXCursor_TypeRef: 152 return MakeCXType(QualType(getCursorTypeRef(C).first->getTypeForDecl(), 153 0), 154 TU); 155 156 case CXCursor_CXXBaseSpecifier: 157 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU); 158 159 case CXCursor_ObjCProtocolRef: 160 case CXCursor_TemplateRef: 161 case CXCursor_NamespaceRef: 162 case CXCursor_MemberRef: 163 case CXCursor_OverloadedDeclRef: 164 default: 165 break; 166 } 167 168 return MakeCXType(QualType(), TU); 169 } 170 171 return MakeCXType(QualType(), TU); 172} 173 174CXType clang_getCanonicalType(CXType CT) { 175 if (CT.kind == CXType_Invalid) 176 return CT; 177 178 QualType T = GetQualType(CT); 179 CXTranslationUnit TU = GetTU(CT); 180 181 if (T.isNull()) 182 return MakeCXType(QualType(), GetTU(CT)); 183 184 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 185 return MakeCXType(AU->getASTContext().getCanonicalType(T), TU); 186} 187 188CXType clang_getPointeeType(CXType CT) { 189 QualType T = GetQualType(CT); 190 const Type *TP = T.getTypePtrOrNull(); 191 192 if (!TP) 193 return MakeCXType(QualType(), GetTU(CT)); 194 195 switch (TP->getTypeClass()) { 196 case Type::Pointer: 197 T = cast<PointerType>(TP)->getPointeeType(); 198 break; 199 case Type::BlockPointer: 200 T = cast<BlockPointerType>(TP)->getPointeeType(); 201 break; 202 case Type::LValueReference: 203 case Type::RValueReference: 204 T = cast<ReferenceType>(TP)->getPointeeType(); 205 break; 206 case Type::ObjCObjectPointer: 207 T = cast<ObjCObjectPointerType>(TP)->getPointeeType(); 208 break; 209 default: 210 T = QualType(); 211 break; 212 } 213 return MakeCXType(T, GetTU(CT)); 214} 215 216CXCursor clang_getTypeDeclaration(CXType CT) { 217 if (CT.kind == CXType_Invalid) 218 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 219 220 QualType T = GetQualType(CT); 221 const Type *TP = T.getTypePtrOrNull(); 222 223 if (!TP) 224 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 225 226 Decl *D = 0; 227 228try_again: 229 switch (TP->getTypeClass()) { 230 case Type::Typedef: 231 D = cast<TypedefType>(TP)->getDecl(); 232 break; 233 case Type::ObjCObject: 234 D = cast<ObjCObjectType>(TP)->getInterface(); 235 break; 236 case Type::ObjCInterface: 237 D = cast<ObjCInterfaceType>(TP)->getDecl(); 238 break; 239 case Type::Record: 240 case Type::Enum: 241 D = cast<TagType>(TP)->getDecl(); 242 break; 243 case Type::TemplateSpecialization: 244 if (const RecordType *Record = TP->getAs<RecordType>()) 245 D = Record->getDecl(); 246 else 247 D = cast<TemplateSpecializationType>(TP)->getTemplateName() 248 .getAsTemplateDecl(); 249 break; 250 251 case Type::InjectedClassName: 252 D = cast<InjectedClassNameType>(TP)->getDecl(); 253 break; 254 255 // FIXME: Template type parameters! 256 257 case Type::Elaborated: 258 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull(); 259 goto try_again; 260 261 default: 262 break; 263 } 264 265 if (!D) 266 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); 267 268 return cxcursor::MakeCXCursor(D, GetTU(CT)); 269} 270 271CXString clang_getTypeKindSpelling(enum CXTypeKind K) { 272 const char *s = 0; 273#define TKIND(X) case CXType_##X: s = "" #X ""; break 274 switch (K) { 275 TKIND(Invalid); 276 TKIND(Unexposed); 277 TKIND(Void); 278 TKIND(Bool); 279 TKIND(Char_U); 280 TKIND(UChar); 281 TKIND(Char16); 282 TKIND(Char32); 283 TKIND(UShort); 284 TKIND(UInt); 285 TKIND(ULong); 286 TKIND(ULongLong); 287 TKIND(UInt128); 288 TKIND(Char_S); 289 TKIND(SChar); 290 case CXType_WChar: s = "WChar"; break; 291 TKIND(Short); 292 TKIND(Int); 293 TKIND(Long); 294 TKIND(LongLong); 295 TKIND(Int128); 296 TKIND(Float); 297 TKIND(Double); 298 TKIND(LongDouble); 299 TKIND(NullPtr); 300 TKIND(Overload); 301 TKIND(Dependent); 302 TKIND(ObjCId); 303 TKIND(ObjCClass); 304 TKIND(ObjCSel); 305 TKIND(Complex); 306 TKIND(Pointer); 307 TKIND(BlockPointer); 308 TKIND(LValueReference); 309 TKIND(RValueReference); 310 TKIND(Record); 311 TKIND(Enum); 312 TKIND(Typedef); 313 TKIND(ObjCInterface); 314 TKIND(ObjCObjectPointer); 315 TKIND(FunctionNoProto); 316 TKIND(FunctionProto); 317 } 318#undef TKIND 319 return cxstring::createCXString(s); 320} 321 322unsigned clang_equalTypes(CXType A, CXType B) { 323 return A.data[0] == B.data[0] && A.data[1] == B.data[1];; 324} 325 326CXType clang_getResultType(CXType X) { 327 QualType T = GetQualType(X); 328 if (!T.getTypePtrOrNull()) 329 return MakeCXType(QualType(), GetTU(X)); 330 331 if (const FunctionType *FD = T->getAs<FunctionType>()) 332 return MakeCXType(FD->getResultType(), GetTU(X)); 333 334 return MakeCXType(QualType(), GetTU(X)); 335} 336 337CXType clang_getCursorResultType(CXCursor C) { 338 if (clang_isDeclaration(C.kind)) { 339 Decl *D = cxcursor::getCursorDecl(C); 340 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 341 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C)); 342 343 return clang_getResultType(clang_getCursorType(C)); 344 } 345 346 return MakeCXType(QualType(), cxcursor::getCursorTU(C)); 347} 348 349unsigned clang_isPODType(CXType X) { 350 QualType T = GetQualType(X); 351 if (!T.getTypePtrOrNull()) 352 return 0; 353 return T->isPODType() ? 1 : 0; 354} 355 356CXString clang_getDeclObjCTypeEncoding(CXCursor C) { 357 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) 358 return cxstring::createCXString(""); 359 360 Decl *D = static_cast<Decl*>(C.data[0]); 361 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]); 362 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData); 363 ASTContext &Ctx = AU->getASTContext(); 364 std::string encoding; 365 366 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 367 Ctx.getObjCEncodingForMethodDecl(OMD, encoding); 368 else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) 369 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding); 370 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 371 Ctx.getObjCEncodingForFunctionDecl(FD, encoding); 372 else { 373 QualType Ty; 374 if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) 375 Ty = QualType(TD->getTypeForDecl(), 0); 376 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 377 Ty = VD->getType(); 378 else return cxstring::createCXString("?"); 379 Ctx.getObjCEncodingForType(Ty, encoding); 380 } 381 382 return cxstring::createCXString(encoding); 383} 384 385} // end: extern "C" 386