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