diff options
| author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2016-12-01 23:41:27 +0000 |
|---|---|---|
| committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2016-12-01 23:41:27 +0000 |
| commit | 5dda1128f17b6a79740d9f549bac4a3db5d45ac2 (patch) | |
| tree | 289f9603e568037a430aa86065d790bef394d4aa | |
| parent | 734c59d501315192e12d9b6450139f5b02c2f8cb (diff) | |
| download | bcm5719-llvm-5dda1128f17b6a79740d9f549bac4a3db5d45ac2.tar.gz bcm5719-llvm-5dda1128f17b6a79740d9f549bac4a3db5d45ac2.zip | |
[libclang] Add APIs to check the result of an integer expression in CXEvalResult without overflow
Patch by Emilio Cobos Álvarez!
See https://reviews.llvm.org/D26788
llvm-svn: 288438
| -rw-r--r-- | clang/include/clang-c/Index.h | 21 | ||||
| -rw-r--r-- | clang/test/Index/evaluate-cursor.cpp | 14 | ||||
| -rw-r--r-- | clang/tools/c-index-test/c-index-test.c | 10 | ||||
| -rw-r--r-- | clang/tools/libclang/CIndex.cpp | 39 | ||||
| -rw-r--r-- | clang/tools/libclang/libclang.exports | 3 |
5 files changed, 81 insertions, 6 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 1f132dea5ec..050c42a3738 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 36 +#define CINDEX_VERSION_MINOR 37 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -5266,6 +5266,25 @@ CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E); CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E); /** + * \brief Returns the evaluation result as a long long integer if the + * kind is Int. This prevents overflows that may happen if the result is + * returned with clang_EvalResult_getAsInt. + */ +CINDEX_LINKAGE long long clang_EvalResult_getAsLongLong(CXEvalResult E); + +/** + * \brief Returns a non-zero value if the kind is Int and the evaluation + * result resulted in an unsigned integer. + */ +CINDEX_LINKAGE unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E); + +/** + * \brief Returns the evaluation result as an unsigned integer if + * the kind is Int and clang_EvalResult_isUnsignedInt is non-zero. + */ +CINDEX_LINKAGE unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E); + +/** * \brief Returns the evaluation result as double if the * kind is double. */ diff --git a/clang/test/Index/evaluate-cursor.cpp b/clang/test/Index/evaluate-cursor.cpp index 28a9c368795..39fc9db98a3 100644 --- a/clang/test/Index/evaluate-cursor.cpp +++ b/clang/test/Index/evaluate-cursor.cpp @@ -15,6 +15,12 @@ void goo() { int a = __LINE__; } +unsigned long long foo_int = 1ull << 60; + +unsigned long long HUGE = 1ull << 63; + +long long HUGE_NEG = -(1ll << 35); + // 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 @@ -28,3 +34,11 @@ void goo() { // CHECK-MACRO: [function macro] // CHECK-MACRO: [function macro] // CHECK-MACRO: [builtin macro] + +// RUN: c-index-test -evaluate-cursor-at=%s:18:20 \ +// RUN: -evaluate-cursor-at=%s:20:20 \ +// RUN: -evaluate-cursor-at=%s:22:11 \ +// RUN: -std=c++11 %s | FileCheck -check-prefix=CHECK-LONG %s +// CHECK-LONG: unsigned, Value: 1152921504606846976 +// CHECK-LONG: unsigned, Value: 9223372036854775808 +// CHECK-LONG: Value: -34359738368 diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 2878ba26aff..de87351059f 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -2462,8 +2462,14 @@ 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); + printf("Kind: Int, "); + if (clang_EvalResult_isUnsignedInt(result)) { + unsigned long long val = clang_EvalResult_getAsUnsigned(result); + printf("unsigned, Value: %llu", val); + } else { + long long val = clang_EvalResult_getAsLongLong(result); + printf("Value: %lld", val); + } break; } case CXEval_Float: diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 4ed6b0ecea1..72eb4018490 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -3518,10 +3518,12 @@ static StringLiteral* getCFSTR_value(CallExpr *callExpr) { struct ExprEvalResult { CXEvalResultKind EvalType; union { - int intVal; + unsigned long long unsignedVal; + long long intVal; double floatVal; char *stringVal; } EvalData; + bool IsUnsignedInt; ~ExprEvalResult() { if (EvalType != CXEval_UnExposed && EvalType != CXEval_Float && EvalType != CXEval_Int) { @@ -3542,10 +3544,32 @@ CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E) { } int clang_EvalResult_getAsInt(CXEvalResult E) { + return clang_EvalResult_getAsLongLong(E); +} + +long long clang_EvalResult_getAsLongLong(CXEvalResult E) { + if (!E) { + return 0; + } + ExprEvalResult *Result = (ExprEvalResult*)E; + if (Result->IsUnsignedInt) + return Result->EvalData.unsignedVal; + return Result->EvalData.intVal; +} + +unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E) { + return ((ExprEvalResult *)E)->IsUnsignedInt; +} + +unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E) { if (!E) { return 0; } - return ((ExprEvalResult *)E)->EvalData.intVal; + + ExprEvalResult *Result = (ExprEvalResult*)E; + if (Result->IsUnsignedInt) + return Result->EvalData.unsignedVal; + return Result->EvalData.intVal; } double clang_EvalResult_getAsDouble(CXEvalResult E) { @@ -3576,10 +3600,19 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { CallExpr *callExpr; auto result = llvm::make_unique<ExprEvalResult>(); result->EvalType = CXEval_UnExposed; + result->IsUnsignedInt = false; if (ER.Val.isInt()) { result->EvalType = CXEval_Int; - result->EvalData.intVal = ER.Val.getInt().getExtValue(); + + auto& val = ER.Val.getInt(); + if (val.isUnsigned()) { + result->IsUnsignedInt = true; + result->EvalData.unsignedVal = val.getZExtValue(); + } else { + result->EvalData.intVal = val.getExtValue(); + } + return result.release(); } diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 6df933a61e6..222cb678395 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -335,6 +335,9 @@ clang_Cursor_hasAttrs clang_Cursor_Evaluate clang_EvalResult_getKind clang_EvalResult_getAsInt +clang_EvalResult_getAsLongLong +clang_EvalResult_getAsUnsigned +clang_EvalResult_isUnsignedInt clang_EvalResult_getAsDouble clang_EvalResult_getAsStr clang_EvalResult_dispose |

