rsmith added inline comments.

================
Comment at: clang/include/clang/AST/Expr.h:670-672
+  /// Evaluate an expression that is required to be a core constant expression.
+  bool EvaluateAsCoreConstExpr(EvalResult &Result, QualType ParamType,
+                               CCEKind CCE, const ASTContext &Ctx) const;
----------------
rnk wrote:
> rsmith wrote:
> > Seems strange to pass a converted constant expression kind to an 'evaluate 
> > as core constant expression' function. And it seems like we don't need the 
> > kind here, just an "evaluating for emission w/relocations" vs "evaluating 
> > for mangling" enum.
> > 
> > Also, we need to evaluate non-type template arguments as constant 
> > expressions, not just as core constant expressions, which the 
> > implementation does, but the name and comment here don't reflect. (The 
> > difference is that you can't result in a pointer/reference to a temporary 
> > or automatic / thread storage duration entity.)
> So... what are these things? Converted constant expressions? What are we 
> evaluating them as? I guess they're not rvalues or lvalues.
I think this should just be called `EvaluateAsConstantExpr`, and you should 
drop all the "core"s throughout. The difference between a constant expression 
and a core constant expression is that a core constant expression allows the 
evaluated value to refer to entities with automatic storage duration etc, which 
is exactly the case you want to disallow here :)

I also don't think you need the `ParamType`, and can instead just look at 
whether the expression itself is an rvalue.


================
Comment at: clang/include/clang/AST/Expr.h:663
+  bool EvaluateAsCoreConstExpr(EvalResult &Result, QualType ParamType,
+                               bool IsTemplateArg, const ASTContext &Ctx) 
const;
+
----------------
I would prefer an `enum { EvaluateForCodeGen, EvaluateForMangling }` over a 
bool `IsTemplateArg`; I would not be surprised if we find other cases where we 
want to evaluate an expression for mangling purposes only.


================
Comment at: clang/lib/AST/ExprConstant.cpp:707
 
+      /// Evaluate as a C++17 non-type template argument, which is a core
+      /// constant expression with a special case for dllimport declarations.
----------------
No "core" here.


================
Comment at: clang/lib/AST/ExprConstant.cpp:709
+      /// constant expression with a special case for dllimport declarations.
+      EM_TemplateArgument,
+
----------------
I don't think we need this. See below.


================
Comment at: clang/lib/AST/ExprConstant.cpp:10384-10385
+    if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects ||
+        !CheckLValueConstantExpression(
+            Info, getExprLoc(), Ctx.getLValueReferenceType(getType()), LV))
+      return false;
----------------
Instead of a new `EvaluationMode` which is actually not used by evaluation, we 
could pass a parameter into `CheckLValueConstantExpression` to indicate if 
we're in the "for-mangling" mode.


================
Comment at: clang/lib/AST/ExprConstant.cpp:10397
+  EvalInfo Info(Ctx, Result, EM);
+  return ::EvaluateAsRValue(Info, this, Result.Val);
+}
----------------
If you switch from using `ParamType->isReferenceType()` to asking the 
expression for its value category, you don't need the 
implicit-lvalue-to-rvalue-conversion semantics of `EvaluateAsRValue`, and can 
just call `::Evaluate` here followed by a call to `CheckConstantExpression` 
(passing the latter the `IsTemplateArg` flag).

In fact, you don't need the separate case for lvalues above, either, since 
`::Evaluate` does the right thing for an lvalue expression by itself.


================
Comment at: clang/lib/Sema/SemaOverload.cpp:5401
 
-  if ((T->isReferenceType()
-           ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
-           : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
+  if (!Result.get()->EvaluateAsNonTypeTemplateArgument(Eval, T, S.Context) ||
       (RequireInt && !Eval.Val.isInt())) {
----------------
rnk wrote:
> rsmith wrote:
> > Don't we get here for `CCEKind`s other than the non-type template argument 
> > case?
> You're right, but I wasn't able to construct a test case where we would call 
> `CheckConvertedConstantExpression` and we would reject it today because it is 
> dllimported. This was my best idea, using `if constexpr`:
> ```
> struct __declspec(dllimport) Foo {
>   static constexpr bool imported_foo = true;
> };
> const bool some_bool = false;
> const bool *f() {
>   if constexpr (Foo::imported_foo) {
>     return &Foo::imported_foo;
>   } else {
>     return &some_bool;
>   }
> }
> ```
> 
> Any other ideas on how to get more coverage of this path through 
> CheckConvertedConstantExpression?
All the other forms of `CCEKind` also set `RequireInt` to `true`, and so any 
case your check catches would also be caught on the line below.


https://reviews.llvm.org/D43320



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to