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