[PATCH] D108479: [Clang] Add __builtin_addressof_nocfi

Sami Tolvanen via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 23 09:51:55 PST 2021


samitolvanen added a comment.

In D108479#3140688 <https://reviews.llvm.org/D108479#3140688>, @rjmccall wrote:

> In D108479#3140638 <https://reviews.llvm.org/D108479#3140638>, @samitolvanen wrote:
>
>> Sure, I can take a look at how that would work. Basically, in `PointerExprEvaluator::VisitBuiltinCallExpr` we should not evaluate the l-value and just leave it at `Result.set(E)`?
>
> Yes, exactly.  Since the builtin already requires a constant operand in non-dependent contexts, that should be enough.

This does indeed solve comparison issues and allows me to drop the changes to `APValue`, but it breaks initializing globals in C because Clang doesn't know the expression is a compile-time constant:

  $ cat test.c
  void a() {}
  const void *p = __builtin_function_start(a);
  $ clang -c test.c
  test.c:2:17: error: initializer element is not a compile-time constant
  const void *p = __builtin_function_start(a);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~
  1 error generated.

I worked around this for now by explicitly allowing `__builtin_function_start` in `CheckLValueConstantExpression`, but this seems terribly hacky. What would be the correct way to solve this issue?



================
Comment at: clang/lib/Sema/SemaChecking.cpp:208
+    if (UnaryOp->getOpcode() == UnaryOperator::Opcode::UO_AddrOf)
+      E = UnaryOp->getSubExpr();
+
----------------
rjmccall wrote:
> It would be more general to allow any expression that we can constant-evaluate to a specific function / member function reference.  That allows callers to do stuff like `__builtin_function_start((int (A::*)() const) &A::x)` to resolve overloaded function references.
> 
> You should delay this check if the operand is value-dependent.
> It would be more general to allow any expression that we can constant-evaluate to a specific function / member function reference.  That allows callers to do stuff like `__builtin_function_start((int (A::*)() const) &A::x)` to resolve overloaded function references.

I looked into using `Expr::EvaluateAsConstantExpr` here and while it works, I'm not sure if allowing arbitrary expressions as the argument provides any value. We can allow resolving overloaded function references without constant-evaluating the expression (and I added tests for this). Did you have any other use cases in mind where this might be useful?


================
Comment at: clang/lib/Sema/SemaChecking.cpp:221
+  if (ResultType.isNull())
+    return true;
+
----------------
rjmccall wrote:
> I think we decided that the result type should be `void*`.  Are there other semantic checks from `CheckAddressOfOperand` that still meaningfully apply?
I thought `Sema::checkAddressOfFunctionIsAvailable` would be useful.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108479/new/

https://reviews.llvm.org/D108479



More information about the cfe-commits mailing list