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