diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 3d49f73a56762..548405a53dfac 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -746,6 +746,17 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) { const auto &RHS = S.Stk.pop(); const auto &LHS = S.Stk.pop(); + + // We cannot compare against weak declarations at compile time. + for (const auto &FP : {LHS, RHS}) { + if (!FP.isZero() && FP.getFunction()->getDecl()->isWeak()) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison) + << FP.toDiagnosticString(S.getCtx()); + return false; + } + } + S.Stk.push(Boolean::from(Fn(LHS.compare(RHS)))); return true; } diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp index 38f761f563bef..67fd9036d81e7 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -565,3 +565,13 @@ namespace VariadicOperator { float &fr = c(10); } } + +namespace WeakCompare { + [[gnu::weak]]void weak_method(); + static_assert(weak_method != nullptr, ""); // both-error {{not an integral constant expression}} \ + // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} + + constexpr auto A = &weak_method; + static_assert(A != nullptr, ""); // both-error {{not an integral constant expression}} \ + // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} +}