diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 564ac56b7f0f..52390217b0df 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -1911,7 +1911,8 @@ enum CXCursorKind { CXCursor_CXXFinalAttr = 404, CXCursor_CXXOverrideAttr = 405, CXCursor_AnnotateAttr = 406, - CXCursor_LastAttr = CXCursor_AnnotateAttr, + CXCursor_AsmLabelAttr = 407, + CXCursor_LastAttr = CXCursor_AsmLabelAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -2383,9 +2384,28 @@ enum CXTypeKind { CXType_ObjCObjectPointer = 109, CXType_FunctionNoProto = 110, CXType_FunctionProto = 111, - CXType_ConstantArray = 112 + CXType_ConstantArray = 112, + CXType_Vector = 113 }; +/** + * \brief Describes the calling convention of a function type + */ +enum CXCallingConv { + CXCallingConv_Default = 0, + CXCallingConv_C = 1, + CXCallingConv_X86StdCall = 2, + CXCallingConv_X86FastCall = 3, + CXCallingConv_X86ThisCall = 4, + CXCallingConv_X86Pascal = 5, + CXCallingConv_AAPCS = 6, + CXCallingConv_AAPCS_VFP = 7, + + CXCallingConv_Invalid = 100, + CXCallingConv_Unexposed = 200 +}; + + /** * \brief The type of an element in the abstract syntax tree. * @@ -2400,6 +2420,42 @@ typedef struct { */ CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C); +/** + * \brief Retrieve the underlying type of a typedef declaration. + * + * If the cursor does not reference a typedef declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C); + +/** + * \brief Retrieve the integer type of an enum declaration. + * + * If the cursor does not reference an enum declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C); + +/** + * \brief Retrieve the integer value of an enum constant declaration as a signed + * long long. + * + * If the cursor does not reference an enum constant declaration, LLONG_MIN is returned. + * Since this is also potentially a valid constant value, the kind of the cursor + * must be verified before calling this function. + */ +CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C); + +/** + * \brief Retrieve the integer value of an enum constant declaration as an unsigned + * long long. + * + * If the cursor does not reference an enum constant declaration, ULLONG_MAX is returned. + * Since this is also potentially a valid constant value, the kind of the cursor + * must be verified before calling this function. + */ +CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C); + /** * \determine Determine whether two CXTypes represent the same type. * @@ -2457,14 +2513,45 @@ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C); */ CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); +/** + * \brief Retrieve the calling convention associated with a function type. + * + * If a non-function type is passed in, CXCallingConv_Invalid is returned. + */ +CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T); + /** * \brief Retrieve the result type associated with a function type. + * + * If a non-function type is passed in, an invalid type is returned. */ CINDEX_LINKAGE CXType clang_getResultType(CXType T); /** - * \brief Retrieve the result type associated with a given cursor. This only - * returns a valid type of the cursor refers to a function or method. + * \brief Retrieve the number of non-variadic arguments associated with a function type. + * + * If a non-function type is passed in, UINT_MAX is returned. + */ +CINDEX_LINKAGE unsigned clang_getNumArgTypes(CXType T); + +/** + * \brief Retrieve the type of an argument of a function type. + * + * If a non-function type is passed in or the function does not have enough parameters, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i); + +/** + * \brief Return 1 if the CXType is a variadic function type, and 0 otherwise. + * + */ +CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T); + +/** + * \brief Retrieve the result type associated with a given cursor. + * + * This only returns a valid type if the cursor refers to a function or method. */ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); @@ -2474,6 +2561,22 @@ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); */ CINDEX_LINKAGE unsigned clang_isPODType(CXType T); +/** + * \brief Return the element type of an array, complex, or vector type. + * + * If a type is passed in that is not an array, complex, or vector type, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getElementType(CXType T); + +/** + * \brief Return the number of elements of an array or vector type. + * + * If a type is passed in that is not an array or vector type, + * -1 is returned. + */ +CINDEX_LINKAGE long long clang_getNumElements(CXType T); + /** * \brief Return the element type of an array type. * diff --git a/clang/test/Index/asm-attribute.c b/clang/test/Index/asm-attribute.c new file mode 100644 index 000000000000..f9524598b608 --- /dev/null +++ b/clang/test/Index/asm-attribute.c @@ -0,0 +1,6 @@ +int foo(int x) __asm__("_foo_"); + +// RUN: c-index-test -test-load-source all %s | FileCheck %s +// CHECK: asm-attribute.c:1:5: FunctionDecl=foo:1:5 Extent=[1:1 - 1:32] +// FIXME: Location below. +// CHECK: :0:0: asm label=_foo_ Extent=[1:24 - 1:31] diff --git a/clang/test/Index/vector-types.c b/clang/test/Index/vector-types.c new file mode 100644 index 000000000000..404e4a54d9a5 --- /dev/null +++ b/clang/test/Index/vector-types.c @@ -0,0 +1,6 @@ +int __attribute__((vector_size(16))) x; +typedef int __attribute__((vector_size(16))) int4_t; + +// RUN: c-index-test -test-print-typekind %s | FileCheck %s +// CHECK: VarDecl=x:1:38 typekind=Vector [isPOD=1] +// CHECK: TypedefDecl=int4_t:2:46 (Definition) typekind=Typedef [canonical=Vector] [isPOD=1] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index d2b5ba7ce5d7..e9a67dbfb5b7 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -3012,6 +3012,11 @@ CXString clang_getCursorSpelling(CXCursor C) { return createCXString(AA->getAnnotation()); } + if (C.kind == CXCursor_AsmLabelAttr) { + AsmLabelAttr *AA = cast(cxcursor::getCursorAttr(C)); + return createCXString(AA->getLabel()); + } + return createCXString(""); } @@ -3335,6 +3340,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("attribute(override)"); case CXCursor_AnnotateAttr: return createCXString("attribute(annotate)"); + case CXCursor_AsmLabelAttr: + return createCXString("asm label"); case CXCursor_PreprocessingDirective: return createCXString("preprocessing directive"); case CXCursor_MacroDefinition: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index e9cc372fe0be..b4b9ed9d3003 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -46,6 +46,7 @@ static CXCursorKind GetCursorKind(const Attr *A) { case attr::Final: return CXCursor_CXXFinalAttr; case attr::Override: return CXCursor_CXXOverrideAttr; case attr::Annotate: return CXCursor_AnnotateAttr; + case attr::AsmLabel: return CXCursor_AsmLabelAttr; } return CXCursor_UnexposedAttr; diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 0e62e2734b0c..8dcef4d1a820 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -85,6 +85,7 @@ static CXTypeKind GetTypeKind(QualType T) { TKCASE(FunctionNoProto); TKCASE(FunctionProto); TKCASE(ConstantArray); + TKCASE(Vector); default: return CXType_Unexposed; } @@ -173,6 +174,74 @@ CXType clang_getCursorType(CXCursor C) { return MakeCXType(QualType(), TU); } +CXType clang_getTypedefDeclUnderlyingType(CXCursor C) { + using namespace cxcursor; + CXTranslationUnit TU = cxcursor::getCursorTU(C); + + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + + if (TypedefNameDecl *TD = dyn_cast(D)) { + QualType T = TD->getUnderlyingType(); + return MakeCXType(T, TU); + } + + return MakeCXType(QualType(), TU); + } + + return MakeCXType(QualType(), TU); +} + +CXType clang_getEnumDeclIntegerType(CXCursor C) { + using namespace cxcursor; + CXTranslationUnit TU = cxcursor::getCursorTU(C); + + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + + if (EnumDecl *TD = dyn_cast(D)) { + QualType T = TD->getIntegerType(); + return MakeCXType(T, TU); + } + + return MakeCXType(QualType(), TU); + } + + return MakeCXType(QualType(), TU); +} + +long long clang_getEnumConstantDeclValue(CXCursor C) { + using namespace cxcursor; + + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + + if (EnumConstantDecl *TD = dyn_cast(D)) { + return TD->getInitVal().getSExtValue(); + } + + return LLONG_MIN; + } + + return LLONG_MIN; +} + +unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) { + using namespace cxcursor; + + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + + if (EnumConstantDecl *TD = dyn_cast(D)) { + return TD->getInitVal().getZExtValue(); + } + + return ULLONG_MAX; + } + + return ULLONG_MAX; +} + CXType clang_getCanonicalType(CXType CT) { if (CT.kind == CXType_Invalid) return CT; @@ -332,6 +401,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) { TKIND(FunctionNoProto); TKIND(FunctionProto); TKIND(ConstantArray); + TKIND(Vector); } #undef TKIND return cxstring::createCXString(s); @@ -341,9 +411,80 @@ unsigned clang_equalTypes(CXType A, CXType B) { return A.data[0] == B.data[0] && A.data[1] == B.data[1];; } +unsigned clang_isFunctionTypeVariadic(CXType X) { + QualType T = GetQualType(X); + if (T.isNull()) + return 0; + + if (const FunctionProtoType *FD = T->getAs()) + return (unsigned)FD->isVariadic(); + + if (T->getAs()) + return 1; + + return 0; +} + +CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { + QualType T = GetQualType(X); + if (T.isNull()) + return CXCallingConv_Invalid; + + if (const FunctionType *FD = T->getAs()) { +#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X + switch (FD->getCallConv()) { + TCALLINGCONV(Default); + TCALLINGCONV(C); + TCALLINGCONV(X86StdCall); + TCALLINGCONV(X86FastCall); + TCALLINGCONV(X86ThisCall); + TCALLINGCONV(X86Pascal); + TCALLINGCONV(AAPCS); + TCALLINGCONV(AAPCS_VFP); + default: + return CXCallingConv_Unexposed; + } +#undef TCALLINGCONV + } + + return CXCallingConv_Invalid; +} + +unsigned clang_getNumArgTypes(CXType X) { + QualType T = GetQualType(X); + if (T.isNull()) + return UINT_MAX; + + if (const FunctionProtoType *FD = T->getAs()) { + return FD->getNumArgs(); + } + + if (T->getAs()) { + return 0; + } + + return UINT_MAX; +} + +CXType clang_getArgType(CXType X, unsigned i) { + QualType T = GetQualType(X); + if (T.isNull()) + return MakeCXType(QualType(), GetTU(X)); + + if (const FunctionProtoType *FD = T->getAs()) { + unsigned numArgs = FD->getNumArgs(); + if (i >= numArgs) + return MakeCXType(QualType(), GetTU(X)); + + return MakeCXType(FD->getArgType(i), GetTU(X)); + } + + return MakeCXType(QualType(), GetTU(X)); +} + CXType clang_getResultType(CXType X) { QualType T = GetQualType(X); - if (!T.getTypePtrOrNull()) + if (T.isNull()) return MakeCXType(QualType(), GetTU(X)); if (const FunctionType *FD = T->getAs()) @@ -366,7 +507,7 @@ CXType clang_getCursorResultType(CXCursor C) { unsigned clang_isPODType(CXType X) { QualType T = GetQualType(X); - if (!T.getTypePtrOrNull()) + if (T.isNull()) return 0; CXTranslationUnit TU = GetTU(X); @@ -375,6 +516,49 @@ unsigned clang_isPODType(CXType X) { return T.isPODType(AU->getASTContext()) ? 1 : 0; } +CXType clang_getElementType(CXType CT) { + QualType ET = QualType(); + QualType T = GetQualType(CT); + const Type *TP = T.getTypePtrOrNull(); + + if (TP) { + switch (TP->getTypeClass()) { + case Type::ConstantArray: + ET = cast (TP)->getElementType(); + break; + case Type::Vector: + ET = cast (TP)->getElementType(); + break; + case Type::Complex: + ET = cast (TP)->getElementType(); + break; + default: + break; + } + } + return MakeCXType(ET, GetTU(CT)); +} + +long long clang_getNumElements(CXType CT) { + long long result = -1; + QualType T = GetQualType(CT); + const Type *TP = T.getTypePtrOrNull(); + + if (TP) { + switch (TP->getTypeClass()) { + case Type::ConstantArray: + result = cast (TP)->getSize().getSExtValue(); + break; + case Type::Vector: + result = cast (TP)->getNumElements(); + break; + default: + break; + } + } + return result; +} + CXType clang_getArrayElementType(CXType CT) { QualType ET = QualType(); QualType T = GetQualType(CT); diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index cf261c8f7834..be74f585080e 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -47,6 +47,7 @@ clang_executeOnThread clang_findReferencesInFile clang_findReferencesInFileWithBlock clang_formatDiagnostic +clang_getArgType clang_getArrayElementType clang_getArraySize clang_getCString @@ -96,10 +97,15 @@ clang_getDiagnosticOption clang_getDiagnosticRange clang_getDiagnosticSeverity clang_getDiagnosticSpelling +clang_getElementType +clang_getEnumConstantDeclValue +clang_getEnumConstantDeclUnsignedValue +clang_getEnumDeclIntegerType clang_getExpansionLocation clang_getFile clang_getFileName clang_getFileTime +clang_getFunctionTypeCallingConv clang_getIBOutletCollectionType clang_getIncludedFile clang_getInclusions @@ -109,9 +115,11 @@ clang_getLocationForOffset clang_getNullCursor clang_getNullLocation clang_getNullRange +clang_getNumArgTypes clang_getNumCompletionChunks clang_getNumDiagnostics clang_getNumDiagnosticsInSet +clang_getNumElements clang_getNumOverloadedDecls clang_getOverloadedDecl clang_getOverriddenCursors @@ -134,6 +142,7 @@ clang_getTranslationUnitCursor clang_getTranslationUnitSpelling clang_getTypeDeclaration clang_getTypeKindSpelling +clang_getTypedefDeclUnderlyingType clang_hashCursor clang_IndexAction_create clang_IndexAction_dispose @@ -158,6 +167,7 @@ clang_isCursorDefinition clang_isDeclaration clang_isExpression clang_isFileMultipleIncludeGuarded +clang_isFunctionTypeVariadic clang_isInvalid clang_isPODType clang_isPreprocessing