================
@@ -236,5 +257,338 @@ bool EvaluationResult::checkReturnValue(InterpState &S, 
const Context &Ctx,
   return true;
 }
 
+static bool isGlobalLValue(const Pointer &Ptr) {
+  if (Ptr.isBlockPointer() && Ptr.block()->isDynamic())
+    return true;
+  if (Ptr.isTypeidPointer())
+    return true;
+
+  const Descriptor *Desc = Ptr.getDeclDesc();
+  return ::isGlobalLValue(Desc->asValueDecl(), Desc->asExpr());
+}
+
+/// Check if the given function pointer can be returned from an evaluation.
+static bool checkFunctionPtr(InterpState &S, const Pointer &Ptr,
+                             QualType PtrType, SourceInfo Info,
+                             ConstantExprKind ConstexprKind) {
+  assert(Ptr.isFunctionPointer());
+  const FunctionPointer &FuncPtr = Ptr.asFunctionPointer();
+  const FunctionDecl *FD = FuncPtr.getFunction()->getDecl();
+  // E.g. ObjC block pointers.
+  if (!FD)
+    return true;
+  if (FD->isImmediateFunction()) {
+    S.FFDiag(Info, diag::note_consteval_address_accessible)
+        << !PtrType->isAnyPointerType();
+    S.Note(FD->getLocation(), diag::note_declared_at);
+    return false;
+  }
+
+  // __declspec(dllimport) must be handled very carefully:
+  // We must never initialize an expression with the thunk in C++.
+  // Doing otherwise would allow the same id-expression to yield
+  // different addresses for the same function in different translation
+  // units.  However, this means that we must dynamically initialize the
+  // expression with the contents of the import address table at runtime.
+  //
+  // The C language has no notion of ODR; furthermore, it has no notion of
+  // dynamic initialization.  This means that we are permitted to
+  // perform initialization with the address of the thunk.
+  if (S.getLangOpts().CPlusPlus && !isForManglingOnly(ConstexprKind) &&
+      FD->hasAttr<DLLImportAttr>())
+    // FIXME: Diagnostic!
+    return false;
+  return true;
+}
+
+static bool lvalFields(InterpState &S, const ASTContext &Ctx,
+                       const Pointer &Ptr, QualType PtrType, SourceInfo Info,
+                       ConstantExprKind ConstexprKind,
+                       llvm::SmallPtrSet<const Block *, 4> &CheckedBlocks);
+static bool lval(InterpState &S, const ASTContext &Ctx, const Pointer &Ptr,
+                 QualType PtrType, SourceInfo Info,
+                 ConstantExprKind ConstexprKind,
+                 llvm::SmallPtrSet<const Block *, 4> &CheckedBlocks) {
+  if (Ptr.isFunctionPointer())
+    return checkFunctionPtr(S, Ptr, PtrType, Info, ConstexprKind);
+
+  if (!Ptr.isBlockPointer())
+    return true;
+
+  const Descriptor *DeclDesc = Ptr.block()->getDescriptor();
+  const Expr *BaseE = DeclDesc->asExpr();
+  const ValueDecl *BaseVD = DeclDesc->asValueDecl();
+  assert(BaseE || BaseVD);
+  bool IsReferenceType = PtrType->isReferenceType();
+  bool IsSubObj = !Ptr.isRoot() || (Ptr.inArray() && !Ptr.isArrayRoot());
+
+  if (!isGlobalLValue(Ptr)) {
+    if (S.getLangOpts().CPlusPlus11) {
+      S.FFDiag(Info, diag::note_constexpr_non_global, 1)
+          << IsReferenceType << IsSubObj
+          << !!DeclDesc->asValueDecl() // DeclDesc->IsTemporary
+          << DeclDesc->asValueDecl();
+      const VarDecl *VarD = DeclDesc->asVarDecl();
+      if (VarD && VarD->isConstexpr()) {
+        // Non-static local constexpr variables have unintuitive semantics:
+        //   constexpr int a = 1;
+        //   constexpr const int *p = &a;
+        // ... is invalid because the address of 'a' is not constant. Suggest
+        // adding a 'static' in this case.
+        S.Note(VarD->getLocation(), diag::note_constexpr_not_static)
+            << VarD
+            << FixItHint::CreateInsertion(VarD->getBeginLoc(), "static ");
+      } else {
+        if (const ValueDecl *VD = DeclDesc->asValueDecl())
+          S.Note(VD->getLocation(), diag::note_declared_at);
+        else if (const Expr *E = DeclDesc->asExpr())
+          S.Note(E->getExprLoc(), diag::note_constexpr_temporary_here);
+      }
+    } else {
+      S.FFDiag(Info);
+    }
+    return false;
+  }
+
+  if (const auto *VD = dyn_cast_if_present<VarDecl>(BaseVD)) {
+    // Check if this is a thread-local variable.
+    if (VD->getTLSKind()) {
+      // FIXME: Diagnostic!
----------------
erichkeane wrote:

here too? 

https://github.com/llvm/llvm-project/pull/186045
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to