r257968 - [libclang] Introduce APIs for evaluating a cursor and checking if a macro is builtin/function.
Argyrios Kyrtzidis via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 15 16:20:03 PST 2016
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
More information about the cfe-commits
mailing list