[PATCH] D34992: Emit static constexpr member as available_externally definition

Richard Smith - zygoloid via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 5 16:25:49 PDT 2017


rsmith added a comment.

We've had problems in the past with speculative emission of values like this resulting in us producing invalid symbol references. (Two cases I remember: an `available_externally` symbol references a symbol that should be emitted as `linkonce_odr` but which is not emitted in this TU, and an `available_externally` symbol references a symbol with `hidden` visibility that is actually defined in a different DSO. In both cases, if the value of the `available_externally` symbol is actually used, you end up with a program with an invalid symbol reference.)

I don't immediately see any ways that this change would be susceptible to such a problem, so perhaps our best bet is to try it and see if it actually breaks anything.



================
Comment at: clang/lib/CodeGen/CodeGenModule.cpp:2374
+  llvm::Constant *Init = nullptr;
+  if (D && D->isConstexpr() && !D->isInline() && !D->hasAttr<DLLImportAttr>()) {
+    const VarDecl *InitDecl;
----------------
Applying this for only `constexpr` variables seems unnecessarily conservative; it seems we could equally do this for any variable that is `const` and has no `mutable` fields (though we'd need to check for `EmitConstantInit` failing in the general case).


================
Comment at: clang/lib/CodeGen/CodeGenModule.cpp:2376
+    const VarDecl *InitDecl;
+    const Expr *InitExpr = D->getAnyInitializer(InitDecl);
+    if (InitExpr) {
----------------
ahatanak wrote:
> Does getAnyInitializer ever return a null pointer here when D is a c++11 constexpr?
Only in error cases, which shouldn't get this far.


================
Comment at: clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp:1
+// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
+
----------------
Please also test what happens in C++1z mode, particularly as static constexpr data members are implicitly `inline` there.


================
Comment at: clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp:15
+// CHECK: @_ZL4BAR3 = available_externally constant i32 44,
+static constexpr int BAR3 = 44;
+
----------------
mehdi_amini wrote:
> Looks like I have a bug here, this should be an internal.
I would imagine that we skip promotion of declaration to definition in this case if we already have a definition.

To that end, please add a testcase like this:

```
struct Bar {
  static constexpr int BAZ = 42;
};
auto *use = &Bar::BAZ;
const int Bar::BAZ;
```

... to make sure that we convert the definition of `Bar::BAZ` from `available_externally` to a strong definition (I think we should end up with `weak_odr` here).


https://reviews.llvm.org/D34992





More information about the cfe-commits mailing list