r288438 - [libclang] Add APIs to check the result of an integer expression in CXEvalResult without overflow

Argyrios Kyrtzidis via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 1 15:41:28 PST 2016


Author: akirtzidis
Date: Thu Dec  1 17:41:27 2016
New Revision: 288438

URL: http://llvm.org/viewvc/llvm-project?rev=288438&view=rev
Log:
[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

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/test/Index/evaluate-cursor.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=288438&r1=288437&r2=288438&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Dec  1 17:41:27 2016
@@ -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_Ev
 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.
  */

Modified: cfe/trunk/test/Index/evaluate-cursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/evaluate-cursor.cpp?rev=288438&r1=288437&r2=288438&view=diff
==============================================================================
--- cfe/trunk/test/Index/evaluate-cursor.cpp (original)
+++ cfe/trunk/test/Index/evaluate-cursor.cpp Thu Dec  1 17:41:27 2016
@@ -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

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=288438&r1=288437&r2=288438&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Thu Dec  1 17:41:27 2016
@@ -2462,8 +2462,14 @@ static void display_evaluate_results(CXE
   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:

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=288438&r1=288437&r2=288438&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Dec  1 17:41:27 2016
@@ -3518,10 +3518,12 @@ static StringLiteral* getCFSTR_value(Cal
 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_getKin
 }
 
 int clang_EvalResult_getAsInt(CXEvalResult E) {
+  return clang_EvalResult_getAsLongLong(E);
+}
+
+long long clang_EvalResult_getAsLongLong(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;
+}
+
+unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E) {
+  return ((ExprEvalResult *)E)->IsUnsignedInt;
+}
+
+unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E) {
+  if (!E) {
+    return 0;
+  }
+
+  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* evaluateExp
   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();
   }
 

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=288438&r1=288437&r2=288438&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Thu Dec  1 17:41:27 2016
@@ -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




More information about the cfe-commits mailing list