================
@@ -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