rsmith added inline comments.

================
Comment at: clang/lib/AST/ExprConstant.cpp:711
+
+      /// Evaluate as a constant expression, as per C++11-and-later constexpr
+      /// rules. Stop if we find that the expression is not a constant
----------------
jyknight wrote:
> rsmith wrote:
> > This is not the intent. The evaluator uses the rules of the current 
> > language mode. However, it doesn't enforce the C and C++98 syntactic 
> > restrictions on what can appear in a constant expression, because it turns 
> > out to be cleaner to check those separately rather than to interleave them 
> > with evaluation.
> > 
> > We should probably document this as evaluating following the evaluation 
> > (but not syntactic) constant expression rules of the current language mode.
> I'm not really sure what you mean to distinguish between C/C++98 "evaluation 
> constant expression rules" and the definition of a C/C++98 ICE?
> 
> Perhaps you mean that if evaluation succeeds, it will have produced a value 
> consistent with the rules of the current language, but that it may not 
> produce the diagnostics in all cases it ought to?
> 
> AFAICT, the evaluator is designed to emit diagnostics only for the C++11 (and 
> later) constant expression rules, as well as for inability to evaluate. The 
> diagnostic notes are usually dropped on the floor in C++98 and C modes, as 
> only "fold" is typically used there -- along with the separate CheckICE to 
> produce warnings.
> 
> I believe the only place the diagnostics were being actually emitted in 
> pre-c++11 modes is for the diagnose_if and enable_if attributes' "potential 
> constant expression" check. And there it really seems to me to be using the 
> c++11 evaluation semantics.
> 
> The existence of isCXX11ConstantExpr suggests an intent for the function to 
> provide the C++11 rules, as well, no?
> 
> 
> Perhaps you mean that if evaluation succeeds, it will have produced a value 
> consistent with the rules of the current language, but that it may not 
> produce the diagnostics in all cases it ought to?

The concern I have with this comment is that it describes a happenstance of 
implementation rather than the intent. The intent is certainly *not* that we 
will use the C++11 rules when calling this in C++98 mode, but it just so 
happens that there are no interesting differences there right now.

Looking at this another way, the fact that we only guarantee to produce "not a 
constant expression because" notes in C++11 onwards is unrelated to the 
evaluation mode. Rather, the reason for that is instead because all the 
validity / ICE checking in other language modes is based on the syntactic form 
of the expression (and is checked separately as a result).

As a concrete suggestion, how about something like:

"Evaluate as a constant expression. Stop if we find that the expression is not 
a constant expression. Note that this doesn't enforce the syntactic ICE 
requirements of C and C++98."


================
Comment at: clang/lib/AST/ExprConstant.cpp:952
+    /// with diagnostics.
+    bool keepEvaluatingAfterNote() {
       switch (EvalMode) {
----------------
jyknight wrote:
> rsmith wrote:
> > "Note" is beside the point here. We should be talking about non-constant 
> > expressions; that's what matters.
> Renamed to keepEvaluatingAfterNonConstexpr, updated comment.
Capitalize as "...NonConstExpr" instead, since this is just an abbreviation of 
the term "constant expression", not C++11's notion of "constexpr". (I'd also 
lengthen this to "...NonConstantExpr" or "...NonConstantExpression" to further 
clarify.)


================
Comment at: clang/lib/AST/ExprConstant.cpp:1440-1444
+      if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) {
         Designator.addDeclUnchecked(D, Virtual);
+        return true;
+      }
+      return Info.keepEvaluatingAfterNote();
----------------
jyknight wrote:
> rsmith wrote:
> > `checkSubobject` should return `false` if it produced a diagnostic that 
> > should cause evaluation to halt; this call to `keepEvaluatingAfterNote` 
> > should not be necessary. (And likewise below.)
> Are you sure?
> 
> Today, checkSubobject returns false if it sees something "invalid" -- and the 
> callers seem to depend on that -- but invalid subobject designators are still 
> allowed during evaluation in fold mode.
> 
> E.g., this is valid in C:
> `struct Foo { int x[]; }; struct Foo f; int *g = f.x;`
> 
> But, in C++, `constexpr int *g = f.x;` is an error, diagnosing 
> note_constexpr_unsupported_unsized_array.
> 
> All the LValue code, with its mutable "Result" state, and carrying of a 
> couple different "Invalid" bits off on the side, is really rather confusing!
What I mean is that you should change the code to make what I said be true, if 
necessary. It's the callee's responsibility to say whether we hit something we 
can't evaluate past. The caller should not be guessing that the only reason 
that `checkSubobject` can fail is due to a `CCEDiag` -- if `checkSubobject` 
fails with an `FFDiag`, this will sometimes return `true`, which would be wrong.

Here's how I'd look at it: a `false` value is a token that indicates that 
someone has produced a diagnostic whose severity is such that we don't need to 
keep evaluating. Once that happens, we don't need to re-check whether to keep 
evaluating, because we've already been told that we shouldn't, and we just need 
to propagate that fact to our caller.


================
Comment at: clang/lib/AST/ExprConstant.cpp:710
+      // EM_PotentialConstantExpressionUnevaluated as a duplicate).  This will
+      // be somewhat tricky to change, because LLVM currently verifies that an
+      // expression is a constant expression (possibly strictly with
----------------
LLVM -> Clang (or "we" or similar)


================
Comment at: clang/lib/AST/ExprConstant.cpp:723
+      /// Fold the expression to a constant, using any techniques we can. Stop
+      /// if we hit a side-effect that we can't model, or undefined behavior.
       EM_ConstantFold,
----------------
Do we now guarantee to stop on UB in this mode? We didn't appear to do so 
previously. (Particularly, we'd evaluate past signed overflow and take the 2's 
complement value.)


================
Comment at: clang/lib/AST/ExprConstant.cpp:956
+    /// expression which is not a constant expression? If this returns true,
+    /// then the evaluation will be successful if and only no diagnostics are
+    /// emitted. If it returns false, evaluation can succeed with diagnostics.
----------------
only no -> only if no


================
Comment at: clang/lib/AST/ExprConstant.cpp:1198-1200
+  if (!Info.keepEvaluatingAfterNonConstexpr())
+    return false;
+  return true;
----------------
Simplify to `return Info.keepEvaluating...();`


================
Comment at: clang/lib/AST/ExprConstant.cpp:2527-2529
+  if (!LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee))
+    return false;
   return true;
----------------
Simplify to `return LVal.adjust[...]`


================
Comment at: clang/lib/AST/ExprConstant.cpp:7438
+      return VisitIgnoredBaseExpression(E->getBase());
     }
 
----------------
Nit: drop the braces here.


================
Comment at: clang/lib/AST/ExprConstant.cpp:11490-11492
+  // _is_ a constant expression.  (Note: the above applies in
+  // EM_ConstantExpression mode, which we use here, but not in,
+  // e.g. EM_ConstantFold or others.)
----------------
I don't believe the parenthetical is true: in C++11 or later, we should always 
get a note if and only if the expression is not a constant expression, 
regardless of evaluation mode. Instead, I think the thing you're highlighting 
here is that the return value from `EvaluateAsRValue` does not indicate whether 
the expression is a constant expression unless the evaluation mode is 
`EM_ConstantExpression`.


================
Comment at: clang/lib/AST/ExprConstant.cpp:11495-11496
+
   if (!Diags.empty()) {
-    IsConstExpr = false;
     if (Loc) *Loc = Diags[0].first;
   }
----------------
Combine these two `if`s.


https://reviews.llvm.org/D52939



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D52939: E... James Y Knight via Phabricator via cfe-commits
    • [PATCH] D529... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D529... James Y Knight via Phabricator via cfe-commits
    • [PATCH] D529... James Y Knight via Phabricator via cfe-commits
    • [PATCH] D529... Richard Smith - zygoloid via Phabricator via cfe-commits

Reply via email to