summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang-c/Index.h21
-rw-r--r--clang/test/Index/evaluate-cursor.cpp14
-rw-r--r--clang/tools/c-index-test/c-index-test.c10
-rw-r--r--clang/tools/libclang/CIndex.cpp39
-rw-r--r--clang/tools/libclang/libclang.exports3
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
OpenPOWER on IntegriCloud