[PATCH] D47628: Detect an incompatible VLA pointer assignment

Jeremy Morse via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 5 02:23:31 PDT 2018


This revision was automatically updated to reflect the committed changes.
jmorse marked 2 inline comments as done.
Closed by commit rL333989: Detect an incompatible VLA pointer assignment (authored by jmorse, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D47628?vs=149688&id=149919#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D47628

Files:
  cfe/trunk/lib/AST/ASTContext.cpp
  cfe/trunk/test/Sema/vla.c


Index: cfe/trunk/test/Sema/vla.c
===================================================================
--- cfe/trunk/test/Sema/vla.c
+++ cfe/trunk/test/Sema/vla.c
@@ -76,3 +76,16 @@
   ];
 };
 int (*use_implicitly_declared)() = implicitly_declared; // ok, was implicitly declared at file scope
+
+void VLAPtrAssign(int size) {
+  int array[1][2][3][size][4][5];
+  // This is well formed
+  int (*p)[2][3][size][4][5] = array;
+  // Last array dimension too large
+  int (*p2)[2][3][size][4][6] = array; // expected-warning {{incompatible pointer types}}
+  // Second array dimension too large
+  int (*p3)[20][3][size][4][5] = array; // expected-warning {{incompatible pointer types}}
+
+  // Not illegal in C, program _might_ be well formed if size == 3.
+  int (*p4)[2][size][3][4][5] = array;
+}
Index: cfe/trunk/lib/AST/ASTContext.cpp
===================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp
+++ cfe/trunk/lib/AST/ASTContext.cpp
@@ -8601,16 +8601,46 @@
     QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
     if (ResultType.isNull())
       return {};
+
+    const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
+    const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
+
+    // If either side is a variable array, and both are complete, check whether
+    // the current dimension is definite.
+    if (LVAT || RVAT) {
+      auto SizeFetch = [this](const VariableArrayType* VAT,
+          const ConstantArrayType* CAT)
+          -> std::pair<bool,llvm::APInt> {
+        if (VAT) {
+          llvm::APSInt TheInt;
+          Expr *E = VAT->getSizeExpr();
+          if (E && E->isIntegerConstantExpr(TheInt, *this))
+            return std::make_pair(true, TheInt);
+          else
+            return std::make_pair(false, TheInt);
+        } else if (CAT) {
+            return std::make_pair(true, CAT->getSize());
+        } else {
+            return std::make_pair(false, llvm::APInt());
+        }
+      };
+
+      bool HaveLSize, HaveRSize;
+      llvm::APInt LSize, RSize;
+      std::tie(HaveLSize, LSize) = SizeFetch(LVAT, LCAT);
+      std::tie(HaveRSize, RSize) = SizeFetch(RVAT, RCAT);
+      if (HaveLSize && HaveRSize && !llvm::APInt::isSameValue(LSize, RSize))
+        return {}; // Definite, but unequal, array dimension
+    }
+
     if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
       return LHS;
     if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
       return RHS;
     if (LCAT) return getConstantArrayType(ResultType, LCAT->getSize(),
                                           ArrayType::ArraySizeModifier(), 0);
     if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
                                           ArrayType::ArraySizeModifier(), 0);
-    const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
-    const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
     if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
       return LHS;
     if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47628.149919.patch
Type: text/x-patch
Size: 3144 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180605/885951e2/attachment-0001.bin>


More information about the cfe-commits mailing list