Author: akirtzidis Date: Fri Jan 15 18:20:02 2016 New Revision: 257968 URL: http://llvm.org/viewvc/llvm-project?rev=257968&view=rev Log: [libclang] Introduce APIs for evaluating a cursor and checking if a macro is builtin/function.
rdar://24091595 Added: cfe/trunk/test/Index/evaluate-cursor.cpp Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/tools/c-index-test/c-index-test.c cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/libclang.exports Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=257968&r1=257967&r2=257968&view=diff ============================================================================== --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Fri Jan 15 18:20:02 2016 @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 32 +#define CINDEX_VERSION_MINOR 33 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -2431,6 +2431,11 @@ CINDEX_LINKAGE unsigned clang_isStatemen CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind); /** + * \brief Determine whether the given cursor has any attributes. + */ +CINDEX_LINKAGE unsigned clang_Cursor_hasAttrs(CXCursor C); + +/** * \brief Determine whether the given cursor kind represents an invalid * cursor. */ @@ -3170,6 +3175,24 @@ CINDEX_LINKAGE CXType clang_getCanonical CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T); /** + * \brief Determine whether a CXCursor that is a macro, is + * function like. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroFunctionLike(CXCursor C); + +/** + * \brief Determine whether a CXCursor that is a macro, is a + * builtin one. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C); + +/** + * \brief Determine whether a CXCursor that is a function declaration, is an + * inline declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C); + +/** * \brief Determine whether a CXType has the "volatile" qualifier set, * without looking through typedefs that may have added "volatile" at * a different level. @@ -3199,6 +3222,11 @@ CINDEX_LINKAGE CXCursor clang_getTypeDec CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C); /** + * Returns the Objective-C type encoding for the specified CXType. + */ +CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type); + +/** * \brief Retrieve the spelling of a given CXTypeKind. */ CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); @@ -5077,6 +5105,59 @@ CINDEX_LINKAGE void clang_getInclusions( CXInclusionVisitor visitor, CXClientData client_data); +typedef enum { + CXEval_Int = 1 , + CXEval_Float = 2, + CXEval_ObjCStrLiteral = 3, + CXEval_StrLiteral = 4, + CXEval_CFStr = 5, + CXEval_Other = 6, + + CXEval_UnExposed = 0 + +} CXEvalResultKind ; + +/** + * \brief Evaluation result of a cursor + */ +typedef void * CXEvalResult; + +/** + * \brief If cursor is a statement declaration tries to evaluate the + * statement and if its variable, tries to evaluate its initializer, + * into its corresponding type. + */ +CINDEX_LINKAGE CXEvalResult clang_Cursor_Evaluate(CXCursor C); + +/** + * \brief Returns the kind of the evaluated result. + */ +CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E); + +/** + * \brief Returns the evaluation result as integer if the + * kind is Int. + */ +int clang_EvalResult_getAsInt(CXEvalResult E); + +/** + * \brief Returns the evaluation result as double if the + * kind is double. + */ +double clang_EvalResult_getAsDouble(CXEvalResult E); + +/** + * \brief Returns the evaluation result as a constant string if the + * kind is other than Int or float. User must not free this pointer, + * instead call clang_EvalResult_dispose on the CXEvalResult returned + * by clang_Cursor_Evaluate. + */ +const char* clang_EvalResult_getAsStr(CXEvalResult E); + +/** + * \brief Disposes the created Eval memory. + */ +void clang_EvalResult_dispose(CXEvalResult E); /** * @} */ Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=257968&r1=257967&r2=257968&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jan 15 18:20:02 2016 @@ -5913,7 +5913,7 @@ void ASTContext::getObjCEncodingForStruc QualType *NotEncodedT) const { assert(RDecl && "Expected non-null RecordDecl"); assert(!RDecl->isUnion() && "Should not be called for unions"); - if (!RDecl->getDefinition()) + if (!RDecl->getDefinition() || RDecl->getDefinition()->isInvalidDecl()) return; CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl); Added: cfe/trunk/test/Index/evaluate-cursor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/evaluate-cursor.cpp?rev=257968&view=auto ============================================================================== --- cfe/trunk/test/Index/evaluate-cursor.cpp (added) +++ cfe/trunk/test/Index/evaluate-cursor.cpp Fri Jan 15 18:20:02 2016 @@ -0,0 +1,30 @@ +// Test is line- and column-sensitive. Run lines are below. + +struct Foo { + int x = 10; +}; + +void foo() { + int p = 11; +} + +#define FUNC_MAC(x) x + +void goo() { + int p = FUNC_MAC(1); + int a = __LINE__; +} + +// RUN: c-index-test -evaluate-cursor-at=%s:4:7 \ +// RUN: -evaluate-cursor-at=%s:8:7 \ +// RUN: -evaluate-cursor-at=%s:8:11 -std=c++11 %s | FileCheck %s +// CHECK: Value: 10 +// CHECK: Value: 11 +// CHECK: Value: 11 + +// RUN: c-index-test -get-macro-info-cursor-at=%s:11:9 \ +// RUN: -get-macro-info-cursor-at=%s:14:11 \ +// RUN: -get-macro-info-cursor-at=%s:15:11 -std=c++11 %s | FileCheck -check-prefix=CHECK-MACRO %s +// CHECK-MACRO: [function macro] +// CHECK-MACRO: [function macro] +// CHECK-MACRO: [builtin macro] Modified: cfe/trunk/tools/c-index-test/c-index-test.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=257968&r1=257967&r2=257968&view=diff ============================================================================== --- cfe/trunk/tools/c-index-test/c-index-test.c (original) +++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Jan 15 18:20:02 2016 @@ -2287,7 +2287,11 @@ typedef struct { unsigned column; } CursorSourceLocation; -static int inspect_cursor_at(int argc, const char **argv) { +typedef void (*cursor_handler_t)(CXCursor cursor); + +static int inspect_cursor_at(int argc, const char **argv, + const char *locations_flag, + cursor_handler_t handler) { CXIndex CIdx; int errorCode; struct CXUnsavedFile *unsaved_files = 0; @@ -2301,7 +2305,7 @@ static int inspect_cursor_at(int argc, c unsigned I; /* Count the number of locations. */ - while (strstr(argv[NumLocations+1], "-cursor-at=") == argv[NumLocations+1]) + while (strstr(argv[NumLocations+1], locations_flag) == argv[NumLocations+1]) ++NumLocations; /* Parse the locations. */ @@ -2309,7 +2313,7 @@ static int inspect_cursor_at(int argc, c Locations = (CursorSourceLocation *)malloc( NumLocations * sizeof(CursorSourceLocation)); for (Loc = 0; Loc < NumLocations; ++Loc) { - const char *input = argv[Loc + 1] + strlen("-cursor-at="); + const char *input = argv[Loc + 1] + strlen(locations_flag); if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, &Locations[Loc].line, &Locations[Loc].column, 0, 0))) @@ -2368,72 +2372,7 @@ static int inspect_cursor_at(int argc, c return -1; if (I + 1 == Repeats) { - CXCompletionString completionString = clang_getCursorCompletionString( - Cursor); - CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); - CXString Spelling; - const char *cspell; - unsigned line, column; - clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); - printf("%d:%d ", line, column); - PrintCursor(Cursor, NULL); - PrintCursorExtent(Cursor); - Spelling = clang_getCursorSpelling(Cursor); - cspell = clang_getCString(Spelling); - if (cspell && strlen(cspell) != 0) { - unsigned pieceIndex; - printf(" Spelling=%s (", cspell); - for (pieceIndex = 0; ; ++pieceIndex) { - CXSourceRange range = - clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); - if (clang_Range_isNull(range)) - break; - PrintRange(range, 0); - } - printf(")"); - } - clang_disposeString(Spelling); - if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1) - printf(" Selector index=%d", - clang_Cursor_getObjCSelectorIndex(Cursor)); - if (clang_Cursor_isDynamicCall(Cursor)) - printf(" Dynamic-call"); - if (Cursor.kind == CXCursor_ObjCMessageExpr) { - CXType T = clang_Cursor_getReceiverType(Cursor); - CXString S = clang_getTypeKindSpelling(T.kind); - printf(" Receiver-type=%s", clang_getCString(S)); - clang_disposeString(S); - } - - { - CXModule mod = clang_Cursor_getModule(Cursor); - CXFile astFile; - CXString name, astFilename; - unsigned i, numHeaders; - if (mod) { - astFile = clang_Module_getASTFile(mod); - astFilename = clang_getFileName(astFile); - name = clang_Module_getFullName(mod); - numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod); - printf(" ModuleName=%s (%s) system=%d Headers(%d):", - clang_getCString(name), clang_getCString(astFilename), - clang_Module_isSystem(mod), numHeaders); - clang_disposeString(name); - clang_disposeString(astFilename); - for (i = 0; i < numHeaders; ++i) { - CXFile file = clang_Module_getTopLevelHeader(TU, mod, i); - CXString filename = clang_getFileName(file); - printf("\n%s", clang_getCString(filename)); - clang_disposeString(filename); - } - } - } - - if (completionString != NULL) { - printf("\nCompletion string: "); - print_completion_string(completionString, stdout); - } - printf("\n"); + handler(Cursor); free(Locations[Loc].filename); } } @@ -2447,6 +2386,184 @@ static int inspect_cursor_at(int argc, c return 0; } +static void inspect_print_cursor(CXCursor Cursor) { + CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); + CXCompletionString completionString = clang_getCursorCompletionString( + Cursor); + CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); + CXString Spelling; + const char *cspell; + unsigned line, column; + clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); + printf("%d:%d ", line, column); + PrintCursor(Cursor, NULL); + PrintCursorExtent(Cursor); + Spelling = clang_getCursorSpelling(Cursor); + cspell = clang_getCString(Spelling); + if (cspell && strlen(cspell) != 0) { + unsigned pieceIndex; + printf(" Spelling=%s (", cspell); + for (pieceIndex = 0; ; ++pieceIndex) { + CXSourceRange range = + clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); + if (clang_Range_isNull(range)) + break; + PrintRange(range, 0); + } + printf(")"); + } + clang_disposeString(Spelling); + if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1) + printf(" Selector index=%d", + clang_Cursor_getObjCSelectorIndex(Cursor)); + if (clang_Cursor_isDynamicCall(Cursor)) + printf(" Dynamic-call"); + if (Cursor.kind == CXCursor_ObjCMessageExpr) { + CXType T = clang_Cursor_getReceiverType(Cursor); + CXString S = clang_getTypeKindSpelling(T.kind); + printf(" Receiver-type=%s", clang_getCString(S)); + clang_disposeString(S); + } + + { + CXModule mod = clang_Cursor_getModule(Cursor); + CXFile astFile; + CXString name, astFilename; + unsigned i, numHeaders; + if (mod) { + astFile = clang_Module_getASTFile(mod); + astFilename = clang_getFileName(astFile); + name = clang_Module_getFullName(mod); + numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod); + printf(" ModuleName=%s (%s) system=%d Headers(%d):", + clang_getCString(name), clang_getCString(astFilename), + clang_Module_isSystem(mod), numHeaders); + clang_disposeString(name); + clang_disposeString(astFilename); + for (i = 0; i < numHeaders; ++i) { + CXFile file = clang_Module_getTopLevelHeader(TU, mod, i); + CXString filename = clang_getFileName(file); + printf("\n%s", clang_getCString(filename)); + clang_disposeString(filename); + } + } + } + + if (completionString != NULL) { + printf("\nCompletion string: "); + print_completion_string(completionString, stdout); + } + printf("\n"); +} + +static void display_evaluate_results(CXEvalResult result) { + switch (clang_EvalResult_getKind(result)) { + case CXEval_Int: + { + int val = clang_EvalResult_getAsInt(result); + printf("Kind: Int , Value: %d", val); + break; + } + case CXEval_Float: + { + double val = clang_EvalResult_getAsDouble(result); + printf("Kind: Float , Value: %f", val); + break; + } + case CXEval_ObjCStrLiteral: + { + const char* str = clang_EvalResult_getAsStr(result); + printf("Kind: ObjCString , Value: %s", str); + break; + } + case CXEval_StrLiteral: + { + const char* str = clang_EvalResult_getAsStr(result); + printf("Kind: CString , Value: %s", str); + break; + } + case CXEval_CFStr: + { + const char* str = clang_EvalResult_getAsStr(result); + printf("Kind: CFString , Value: %s", str); + break; + } + default: + printf("Unexposed"); + break; + } +} + +static void inspect_evaluate_cursor(CXCursor Cursor) { + CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); + CXString Spelling; + const char *cspell; + unsigned line, column; + CXEvalResult ER; + + clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); + printf("%d:%d ", line, column); + PrintCursor(Cursor, NULL); + PrintCursorExtent(Cursor); + Spelling = clang_getCursorSpelling(Cursor); + cspell = clang_getCString(Spelling); + if (cspell && strlen(cspell) != 0) { + unsigned pieceIndex; + printf(" Spelling=%s (", cspell); + for (pieceIndex = 0; ; ++pieceIndex) { + CXSourceRange range = + clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); + if (clang_Range_isNull(range)) + break; + PrintRange(range, 0); + } + printf(")"); + } + clang_disposeString(Spelling); + + ER = clang_Cursor_Evaluate(Cursor); + if (!ER) { + printf("Not Evaluatable"); + } else { + display_evaluate_results(ER); + clang_EvalResult_dispose(ER); + } + printf("\n"); +} + +static void inspect_macroinfo_cursor(CXCursor Cursor) { + CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); + CXString Spelling; + const char *cspell; + unsigned line, column; + clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); + printf("%d:%d ", line, column); + PrintCursor(Cursor, NULL); + PrintCursorExtent(Cursor); + Spelling = clang_getCursorSpelling(Cursor); + cspell = clang_getCString(Spelling); + if (cspell && strlen(cspell) != 0) { + unsigned pieceIndex; + printf(" Spelling=%s (", cspell); + for (pieceIndex = 0; ; ++pieceIndex) { + CXSourceRange range = + clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); + if (clang_Range_isNull(range)) + break; + PrintRange(range, 0); + } + printf(")"); + } + clang_disposeString(Spelling); + + if (clang_Cursor_isMacroBuiltin(Cursor)) { + printf("[builtin macro]"); + } else if (clang_Cursor_isMacroFunctionLike(Cursor)) { + printf("[function macro]"); + } + printf("\n"); +} + static enum CXVisitorResult findFileRefsVisit(void *context, CXCursor cursor, CXSourceRange range) { if (clang_Range_isNull(range)) @@ -4121,6 +4238,8 @@ static void print_usage(void) { "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n" " c-index-test -code-completion-timing=<site> <compiler arguments>\n" " c-index-test -cursor-at=<site> <compiler arguments>\n" + " c-index-test -evaluate-cursor-at=<site> <compiler arguments>\n" + " c-index-test -get-macro-info-cursor-at=<site> <compiler arguments>\n" " c-index-test -file-refs-at=<site> <compiler arguments>\n" " c-index-test -file-includes-in=<filename> <compiler arguments>\n"); fprintf(stderr, @@ -4186,7 +4305,13 @@ int cindextest_main(int argc, const char if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1]) return perform_code_completion(argc, argv, 1); if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1]) - return inspect_cursor_at(argc, argv); + return inspect_cursor_at(argc, argv, "-cursor-at=", inspect_print_cursor); + if (argc > 2 && strstr(argv[1], "-evaluate-cursor-at=") == argv[1]) + return inspect_cursor_at(argc, argv, "-evaluate-cursor-at=", + inspect_evaluate_cursor); + if (argc > 2 && strstr(argv[1], "-get-macro-info-cursor-at=") == argv[1]) + return inspect_cursor_at(argc, argv, "-get-macro-info-cursor-at=", + inspect_macroinfo_cursor); if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1]) return find_file_refs_at(argc, argv); if (argc > 2 && strstr(argv[1], "-file-includes-in=") == argv[1]) Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=257968&r1=257967&r2=257968&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Fri Jan 15 18:20:02 2016 @@ -3289,6 +3289,329 @@ enum CXErrorCode clang_parseTranslationU return result; } +CXString clang_Type_getObjCEncoding(CXType CT) { + CXTranslationUnit tu = static_cast<CXTranslationUnit>(CT.data[1]); + ASTContext &Ctx = getASTUnit(tu)->getASTContext(); + std::string encoding; + Ctx.getObjCEncodingForType(QualType::getFromOpaquePtr(CT.data[0]), + encoding); + + return cxstring::createDup(encoding); +} + +static const IdentifierInfo *getMacroIdentifier(CXCursor C) { + if (C.kind == CXCursor_MacroDefinition) { + if (const MacroDefinitionRecord *MDR = getCursorMacroDefinition(C)) + return MDR->getName(); + } else if (C.kind == CXCursor_MacroExpansion) { + MacroExpansionCursor ME = getCursorMacroExpansion(C); + return ME.getName(); + } + return nullptr; +} + +unsigned clang_Cursor_isMacroFunctionLike(CXCursor C) { + const IdentifierInfo *II = getMacroIdentifier(C); + if (!II) { + return false; + } + ASTUnit *ASTU = getCursorASTUnit(C); + Preprocessor &PP = ASTU->getPreprocessor(); + if (const MacroInfo *MI = PP.getMacroInfo(II)) + return MI->isFunctionLike(); + return false; +} + +unsigned clang_Cursor_isMacroBuiltin(CXCursor C) { + const IdentifierInfo *II = getMacroIdentifier(C); + if (!II) { + return false; + } + ASTUnit *ASTU = getCursorASTUnit(C); + Preprocessor &PP = ASTU->getPreprocessor(); + if (const MacroInfo *MI = PP.getMacroInfo(II)) + return MI->isBuiltinMacro(); + return false; +} + +unsigned clang_Cursor_isFunctionInlined(CXCursor C) { + const Decl *D = getCursorDecl(C); + const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); + if (!FD) { + return false; + } + return FD->isInlined(); +} + +static StringLiteral* getCFSTR_value(CallExpr *callExpr) { + if (callExpr->getNumArgs() != 1) { + return nullptr; + } + + StringLiteral *S = nullptr; + auto *arg = callExpr->getArg(0); + if (arg->getStmtClass() == Stmt::ImplicitCastExprClass) { + ImplicitCastExpr *I = static_cast<ImplicitCastExpr *>(arg); + auto *subExpr = I->getSubExprAsWritten(); + + if(subExpr->getStmtClass() != Stmt::StringLiteralClass){ + return nullptr; + } + + S = static_cast<StringLiteral *>(I->getSubExprAsWritten()); + } else if (arg->getStmtClass() == Stmt::StringLiteralClass) { + S = static_cast<StringLiteral *>(callExpr->getArg(0)); + } else { + return nullptr; + } + return S; +} + +typedef struct { + CXEvalResultKind EvalType; + union { + int intVal; + double floatVal; + char *stringVal; + } EvalData; +} ExprEvalResult; + +void clang_EvalResult_dispose(CXEvalResult E) { + ExprEvalResult *ER = (ExprEvalResult *)E; + if (ER) { + CXEvalResultKind evalType = ER->EvalType; + + if (evalType != CXEval_UnExposed && evalType != CXEval_Float && + evalType != CXEval_Int && ER->EvalData.stringVal) { + free((void *) ER->EvalData.stringVal); + } + free((void *)ER); + } +} + +CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E) { + if (!E) { + return CXEval_UnExposed; + } + return ((ExprEvalResult *)E)->EvalType; +} + +int clang_EvalResult_getAsInt(CXEvalResult E) { + if (!E) { + return 0; + } + return ((ExprEvalResult *)E)->EvalData.intVal; +} + +double clang_EvalResult_getAsDouble(CXEvalResult E) { + if (!E) { + return 0; + } + return ((ExprEvalResult *)E)->EvalData.floatVal; +} + +const char* clang_EvalResult_getAsStr(CXEvalResult E) { + if (!E) { + return nullptr; + } + return ((ExprEvalResult *)E)->EvalData.stringVal; +} + +static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { + Expr::EvalResult ER; + ASTContext &ctx = getCursorContext(C); + if (!expr) { + return nullptr; + } + expr = expr->IgnoreParens(); + bool res = expr->EvaluateAsRValue(ER, ctx); + QualType rettype; + CallExpr *callExpr; + ExprEvalResult *result = (ExprEvalResult *) malloc(sizeof(ExprEvalResult)); + if (!result) { + return nullptr; + } + result->EvalType = CXEval_UnExposed; + + if (res) { + + if (ER.Val.isInt()) { + result->EvalType = CXEval_Int; + result->EvalData.intVal = ER.Val.getInt().getExtValue(); + return result; + } else if (ER.Val.isFloat()) { + + llvm::SmallVector<char, 100> Buffer; + ER.Val.getFloat().toString(Buffer); + std::string floatStr(Buffer.data(), Buffer.size()); + result->EvalType = CXEval_Float; + bool ignored; + llvm::APFloat apFloat = ER.Val.getFloat(); + apFloat.convert(llvm::APFloat::IEEEdouble, + llvm::APFloat::rmNearestTiesToEven, &ignored); + result->EvalData.floatVal = apFloat.convertToDouble(); + return result; + + } else if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { + + const ImplicitCastExpr *I = dyn_cast<ImplicitCastExpr>(expr); + auto *subExpr = I->getSubExprAsWritten(); + if (subExpr->getStmtClass() == Stmt::StringLiteralClass || + subExpr->getStmtClass() == Stmt::ObjCStringLiteralClass) { + + const StringLiteral *StrE = nullptr; + const ObjCStringLiteral *ObjCExpr; + ObjCExpr = dyn_cast<ObjCStringLiteral>(subExpr); + + if (ObjCExpr) { + StrE = ObjCExpr->getString(); + result->EvalType = CXEval_ObjCStrLiteral; + } else { + StrE = cast<StringLiteral>(I->getSubExprAsWritten()); + result->EvalType = CXEval_StrLiteral; + } + + std::string strRef(StrE->getString().str()); + result->EvalData.stringVal = (char *)malloc(strRef.size()+1); + strncpy((char*)result->EvalData.stringVal, strRef.c_str(), + strRef.size()); + result->EvalData.stringVal[strRef.size()] = '\0'; + return result; + } + + } else if (expr->getStmtClass() == Stmt::ObjCStringLiteralClass || + expr->getStmtClass() == Stmt::StringLiteralClass) { + + const StringLiteral *StrE = nullptr; + const ObjCStringLiteral *ObjCExpr; + ObjCExpr = dyn_cast<ObjCStringLiteral>(expr); + + if (ObjCExpr) { + StrE = ObjCExpr->getString(); + result->EvalType = CXEval_ObjCStrLiteral; + } else { + StrE = cast<StringLiteral>(expr); + result->EvalType = CXEval_StrLiteral; + } + + std::string strRef(StrE->getString().str()); + result->EvalData.stringVal = (char *)malloc(strRef.size()+1); + strncpy((char*)result->EvalData.stringVal, strRef.c_str(), + strRef.size()); + result->EvalData.stringVal[strRef.size()] = '\0'; + return result; + + } else if (expr->getStmtClass() == Stmt::CStyleCastExprClass) { + + CStyleCastExpr *CC = static_cast<CStyleCastExpr *>(expr); + + rettype = CC->getType(); + if (rettype.getAsString() == "CFStringRef" && + CC->getSubExpr()->getStmtClass() == Stmt::CallExprClass) { + + callExpr = static_cast<CallExpr *>(CC->getSubExpr()); + StringLiteral* S = getCFSTR_value(callExpr); + if (S) { + std::string strLiteral(S->getString().str()); + result->EvalType = CXEval_CFStr; + + result->EvalData.stringVal = (char *)malloc(strLiteral.size()+1); + strncpy((char*)result->EvalData.stringVal, strLiteral.c_str(), + strLiteral.size()); + result->EvalData.stringVal[strLiteral.size()] = '\0'; + return result; + } + } + + } else if (expr->getStmtClass() == Stmt::CallExprClass) { + + callExpr = static_cast<CallExpr *>(expr); + rettype = callExpr->getCallReturnType(ctx); + + if (rettype->isVectorType() || callExpr->getNumArgs() > 1) { + return nullptr; + } + if (rettype->isIntegralType(ctx) || rettype->isRealFloatingType()) { + if(callExpr->getNumArgs() == 1 && + !callExpr->getArg(0)->getType()->isIntegralType(ctx)){ + + return nullptr; + } + } else if(rettype.getAsString() == "CFStringRef") { + + StringLiteral* S = getCFSTR_value(callExpr); + if (S) { + std::string strLiteral(S->getString().str()); + result->EvalType = CXEval_CFStr; + result->EvalData.stringVal = (char *)malloc(strLiteral.size()+1); + strncpy((char*)result->EvalData.stringVal, strLiteral.c_str(), + strLiteral.size()); + result->EvalData.stringVal[strLiteral.size()] = '\0'; + return result; + } + } + + } else if (expr->getStmtClass() == Stmt::DeclRefExprClass) { + + DeclRefExpr *D = static_cast<DeclRefExpr *>(expr); + ValueDecl *V = D->getDecl(); + if (V->getKind() == Decl::Function) { + std::string strName(V->getNameAsString()); + result->EvalType = CXEval_Other; + result->EvalData.stringVal = (char *)malloc(strName.size()+1); + strncpy((char*)result->EvalData.stringVal, strName.c_str(), + strName.size()); + result->EvalData.stringVal[strName.size()] = '\0'; + return result; + } + } + + } + + clang_EvalResult_dispose((CXEvalResult *)result); + return nullptr; +} + +CXEvalResult clang_Cursor_Evaluate(CXCursor C) { + const Decl *D = getCursorDecl(C); + if (D) { + const Expr *expr = nullptr; + if (auto *Var = dyn_cast<VarDecl>(D)) { + expr = Var->getInit(); + } else if (auto *Field = dyn_cast<FieldDecl>(D)) { + expr = Field->getInClassInitializer(); + } + if (expr) + return (CXEvalResult)evaluateExpr((Expr *)expr, C); + return nullptr; + } + + const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C)); + if (compoundStmt) { + Expr *expr = nullptr; + for (auto *bodyIterator : compoundStmt->body()) { + if ((expr = dyn_cast<Expr>(bodyIterator))) { + break; + } + } + if (expr) + return (CXEvalResult)evaluateExpr(expr, C); + } + return nullptr; +} + +unsigned clang_Cursor_hasAttrs(CXCursor C) { + const Decl *D = getCursorDecl(C); + if (!D) { + return 0; + } + + if (D->hasAttrs()) { + return 1; + } + + return 0; +} unsigned clang_defaultSaveOptions(CXTranslationUnit TU) { return CXSaveTranslationUnit_None; } Modified: cfe/trunk/tools/libclang/libclang.exports URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=257968&r1=257967&r2=257968&view=diff ============================================================================== --- cfe/trunk/tools/libclang/libclang.exports (original) +++ cfe/trunk/tools/libclang/libclang.exports Fri Jan 15 18:20:02 2016 @@ -320,3 +320,14 @@ clang_VirtualFileOverlay_create clang_VirtualFileOverlay_dispose clang_VirtualFileOverlay_setCaseSensitivity clang_VirtualFileOverlay_writeToBuffer +clang_Type_getObjCEncoding +clang_Cursor_isMacroFunctionLike +clang_Cursor_isMacroBuiltin +clang_Cursor_isFunctionInlined +clang_Cursor_hasAttrs +clang_Cursor_Evaluate +clang_EvalResult_getKind +clang_EvalResult_getAsInt +clang_EvalResult_getAsDouble +clang_EvalResult_getAsStr +clang_EvalResult_dispose _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits