r312108 - Revert "Improve constant expression evaluation of arrays of unknown bound."

Martin Bohme via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 30 03:44:46 PDT 2017


Author: mboehme
Date: Wed Aug 30 03:44:46 2017
New Revision: 312108

URL: http://llvm.org/viewvc/llvm-project?rev=312108&view=rev
Log:
Revert "Improve constant expression evaluation of arrays of unknown bound."

This reverts commit r311970.

Breaks internal tests.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticIDs.h
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=312108&r1=312107&r2=312108&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Wed Aug 30 03:44:46 2017
@@ -127,10 +127,6 @@ def note_constexpr_access_null : Note<
 def note_constexpr_access_past_end : Note<
   "%select{read of|assignment to|increment of|decrement of}0 "
   "dereferenced one-past-the-end pointer is not allowed in a constant expression">;
-def note_constexpr_access_unsized_array : Note<
-  "%select{read of|assignment to|increment of|decrement of}0 "
-  "pointer to element of array without known bound "
-  "is not allowed in a constant expression">;
 def note_constexpr_access_inactive_union_member : Note<
   "%select{read of|assignment to|increment of|decrement of}0 "
   "member %1 of union with %select{active member %3|no active member}2 "
@@ -158,11 +154,6 @@ def note_constexpr_baa_insufficient_alig
 def note_constexpr_baa_value_insufficient_alignment : Note<
   "value of the aligned pointer (%0) is not a multiple of the asserted %1 "
   "%plural{1:byte|:bytes}1">;
-def note_constexpr_unsupported_unsized_array : Note<
-  "array-to-pointer decay of array member without known bound is not supported">;
-def note_constexpr_unsized_array_indexed : Note<
-  "indexing of array without known bound is not allowed "
-  "in a constant expression">;
 
 def warn_integer_constant_overflow : Warning<
   "overflow in expression; result is %0 with type %1">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=312108&r1=312107&r2=312108&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Wed Aug 30 03:44:46 2017
@@ -34,7 +34,7 @@ namespace clang {
       DIAG_SIZE_SERIALIZATION =  120,
       DIAG_SIZE_LEX           =  400,
       DIAG_SIZE_PARSE         =  500,
-      DIAG_SIZE_AST           =  150,
+      DIAG_SIZE_AST           =  110,
       DIAG_SIZE_COMMENT       =  100,
       DIAG_SIZE_SEMA          = 3500,
       DIAG_SIZE_ANALYSIS      =  100

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=312108&r1=312107&r2=312108&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Aug 30 03:44:46 2017
@@ -141,12 +141,6 @@ namespace {
     return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);
   }
 
-  /// The bound to claim that an array of unknown bound has.
-  /// The value in MostDerivedArraySize is undefined in this case. So, set it
-  /// to an arbitrary value that's likely to loudly break things if it's used.
-  static const uint64_t AssumedSizeForUnsizedArray =
-      std::numeric_limits<uint64_t>::max() / 2;
-
   /// Determines if an LValue with the given LValueBase will have an unsized
   /// array in its designator.
   /// Find the path length and type of the most-derived subobject in the given
@@ -154,8 +148,7 @@ namespace {
   static unsigned
   findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
                            ArrayRef<APValue::LValuePathEntry> Path,
-                           uint64_t &ArraySize, QualType &Type, bool &IsArray,
-                           bool &FirstEntryIsUnsizedArray) {
+                           uint64_t &ArraySize, QualType &Type, bool &IsArray) {
     // This only accepts LValueBases from APValues, and APValues don't support
     // arrays that lack size info.
     assert(!isBaseAnAllocSizeCall(Base) &&
@@ -165,18 +158,12 @@ namespace {
 
     for (unsigned I = 0, N = Path.size(); I != N; ++I) {
       if (Type->isArrayType()) {
-        const ArrayType *AT = Ctx.getAsArrayType(Type);
-        Type = AT->getElementType();
+        const ConstantArrayType *CAT =
+            cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
+        Type = CAT->getElementType();
+        ArraySize = CAT->getSize().getZExtValue();
         MostDerivedLength = I + 1;
         IsArray = true;
-
-        if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
-          ArraySize = CAT->getSize().getZExtValue();
-        } else {
-          assert(I == 0 && "unexpected unsized array designator");
-          FirstEntryIsUnsizedArray = true;
-          ArraySize = AssumedSizeForUnsizedArray;
-        }
       } else if (Type->isAnyComplexType()) {
         const ComplexType *CT = Type->castAs<ComplexType>();
         Type = CT->getElementType();
@@ -259,12 +246,10 @@ namespace {
         Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
         if (V.getLValueBase()) {
           bool IsArray = false;
-          bool FirstIsUnsizedArray = false;
           MostDerivedPathLength = findMostDerivedSubobject(
               Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,
-              MostDerivedType, IsArray, FirstIsUnsizedArray);
+              MostDerivedType, IsArray);
           MostDerivedIsArrayElement = IsArray;
-          FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray;
         }
       }
     }
@@ -333,7 +318,7 @@ namespace {
       // The value in MostDerivedArraySize is undefined in this case. So, set it
       // to an arbitrary value that's likely to loudly break things if it's
       // used.
-      MostDerivedArraySize = AssumedSizeForUnsizedArray;
+      MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2;
       MostDerivedPathLength = Entries.size();
     }
     /// Update this designator to refer to the given base or member of this
@@ -365,7 +350,6 @@ namespace {
       MostDerivedArraySize = 2;
       MostDerivedPathLength = Entries.size();
     }
-    void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
     void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
                                    const APSInt &N);
     /// Add N to the address of this subobject.
@@ -373,7 +357,6 @@ namespace {
       if (Invalid || !N) return;
       uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
       if (isMostDerivedAnUnsizedArray()) {
-        diagnoseUnsizedArrayPointerArithmetic(Info, E);
         // Can't verify -- trust that the user is doing the right thing (or if
         // not, trust that the caller will catch the bad behavior).
         // FIXME: Should we reject if this overflows, at least?
@@ -1085,19 +1068,9 @@ bool SubobjectDesignator::checkSubobject
     setInvalid();
     return false;
   }
-  // Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there
-  // must actually be at least one array element; even a VLA cannot have a
-  // bound of zero. And if our index is nonzero, we already had a CCEDiag.
   return true;
 }
 
-void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info,
-                                                                const Expr *E) {
-  Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed);
-  // Do not set the designator as invalid: we can represent this situation,
-  // and correct handling of __builtin_object_size requires us to do so.
-}
-
 void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
                                                     const Expr *E,
                                                     const APSInt &N) {
@@ -1241,6 +1214,8 @@ namespace {
                     IsNullPtr);
       else {
         assert(!InvalidBase && "APValues can't handle invalid LValue bases");
+        assert(!Designator.FirstEntryIsAnUnsizedArray &&
+               "Unsized array with a valid base?");
         V = APValue(Base, Offset, Designator.Entries,
                     Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
       }
@@ -1313,14 +1288,10 @@ namespace {
       if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))
         Designator.addDeclUnchecked(D, Virtual);
     }
-    void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) {
-      if (!Designator.Entries.empty()) {
-        Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array);
-        Designator.setInvalid();
-        return;
-      }
-
-      assert(getType(Base)->isPointerType() || getType(Base)->isArrayType());
+    void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {
+      assert(Designator.Entries.empty() && getType(Base)->isPointerType());
+      assert(isBaseAnAllocSizeCall(Base) &&
+             "Only alloc_size bases can have unsized arrays");
       Designator.FirstEntryIsAnUnsizedArray = true;
       Designator.addUnsizedArrayUnchecked(ElemTy);
     }
@@ -2627,12 +2598,10 @@ findSubobject(EvalInfo &Info, const Expr
   if (Sub.Invalid)
     // A diagnostic will have already been produced.
     return handler.failed();
-  if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) {
+  if (Sub.isOnePastTheEnd()) {
     if (Info.getLangOpts().CPlusPlus11)
-      Info.FFDiag(E, Sub.isOnePastTheEnd()
-                         ? diag::note_constexpr_access_past_end
-                         : diag::note_constexpr_access_unsized_array)
-          << handler.AccessKind;
+      Info.FFDiag(E, diag::note_constexpr_access_past_end)
+        << handler.AccessKind;
     else
       Info.FFDiag(E);
     return handler.failed();
@@ -5491,7 +5460,7 @@ static bool evaluateLValueAsAllocSize(Ev
   Result.setInvalid(E);
 
   QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType();
-  Result.addUnsizedArray(Info, E, Pointee);
+  Result.addUnsizedArray(Info, Pointee);
   return true;
 }
 
@@ -5701,8 +5670,7 @@ bool PointerExprEvaluator::VisitCastExpr
       return true;
     }
   }
-
-  case CK_ArrayToPointerDecay: {
+  case CK_ArrayToPointerDecay:
     if (SubExpr->isGLValue()) {
       if (!evaluateLValue(SubExpr, Result))
         return false;
@@ -5713,13 +5681,12 @@ bool PointerExprEvaluator::VisitCastExpr
         return false;
     }
     // The result is a pointer to the first element of the array.
-    auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType());
-    if (auto *CAT = dyn_cast<ConstantArrayType>(AT))
+    if (const ConstantArrayType *CAT
+          = Info.Ctx.getAsConstantArrayType(SubExpr->getType()))
       Result.addArray(Info, E, CAT);
     else
-      Result.addUnsizedArray(Info, E, AT->getElementType());
+      Result.Designator.setInvalid();
     return true;
-  }
 
   case CK_FunctionToPointerDecay:
     return evaluateLValue(SubExpr, Result);
@@ -5786,7 +5753,7 @@ bool PointerExprEvaluator::visitNonBuilt
 
   Result.setInvalid(E);
   QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
-  Result.addUnsizedArray(Info, E, PointeeTy);
+  Result.addUnsizedArray(Info, PointeeTy);
   return true;
 }
 
@@ -7347,8 +7314,7 @@ static const Expr *ignorePointerCastsAnd
 /// Please note: this function is specialized for how __builtin_object_size
 /// views "objects".
 ///
-/// If this encounters an invalid RecordDecl or otherwise cannot determine the
-/// correct result, it will always return true.
+/// If this encounters an invalid RecordDecl, it will always return true.
 static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
   assert(!LVal.Designator.Invalid);
 
@@ -7379,8 +7345,9 @@ static bool isDesignatorAtObjectEnd(cons
   unsigned I = 0;
   QualType BaseType = getType(Base);
   if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
-    // If we don't know the array bound, conservatively assume we're looking at
-    // the final array element.
+    assert(isBaseAnAllocSizeCall(Base) &&
+           "Unsized array in non-alloc_size call?");
+    // If this is an alloc_size base, we should ignore the initial array index
     ++I;
     BaseType = BaseType->castAs<PointerType>()->getPointeeType();
   }

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=312108&r1=312107&r2=312108&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Wed Aug 30 03:44:46 2017
@@ -604,34 +604,6 @@ static_assert(NATDCArray{}[1][1].n == 0,
 
 }
 
-// FIXME: The rules in this case are unclear, but we conservatively choose to
-// reject any cases where pointer arithmetic is not statically known to be
-// valid.
-namespace ArrayOfUnknownBound {
-  extern int arr[];
-  constexpr int *a = arr;
-  constexpr int *b = &arr[0];
-  static_assert(a == b, "");
-  constexpr int *c = &arr[1]; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
-  constexpr int *d = &a[1]; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
-  constexpr int *e = a + 1; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
-
-  struct X {
-    int a;
-    int b[]; // expected-warning {{C99}}
-  };
-  extern X x;
-  constexpr int *xb = x.b; // expected-error {{constant}} expected-note {{not supported}}
-
-  struct Y { int a; };
-  extern Y yarr[];
-  constexpr Y *p = yarr;
-  constexpr int *q = &p->a;
-
-  extern const int carr[]; // expected-note {{here}}
-  constexpr int n = carr[0]; // expected-error {{constant}} expected-note {{non-constexpr variable}}
-}
-
 namespace DependentValues {
 
 struct I { int n; typedef I V[10]; };




More information about the cfe-commits mailing list