Opened 3 weeks ago

Last modified 41 hours ago

#880 _started defect

Build fails on macOS with Apple Clang 21 ("call to 'makeWindowCallback' is ambiguous") due to duplicate template overloads generated by ConstParamT<T*>

Reported by: guest Owned by: westram
Priority: major Milestone:
Component: global Version: SVN
Keywords: Cc:

Description (last modified by westram)

Operating system: macOS Tahoe 26.2.5 (also reproduced on an earlier Tahoe point release)
ARB version: 7.0.1, built via the arb-project/arb Homebrew tap (arb@7 formula), both stable and —HEAD
Compiler: Apple Clang 21.0.0 (clang-2100.1.1.101),
Target: x86_64-apple-darwin (built under Rosetta on Apple Silicon; same failure occurs natively on arm64)

Description:

ARB fails to compile with Apple's newest Clang (21.0.0), shipped with macOS Tahoe. The build fails in multiple modules (AWTC, AW_NAME, PROBE_DESIGN, MULTI_PROBE) with errors like:

AWTC_submission.cxx:290:19: error: call to 'makeWindowCallback' is ambiguous 290 | aws->callback(makeWindowCallback(ed_save_var_to_file, AWAR_SUBMIT_PARSED, AWAR_SUBMIT_FILE)); | ^~~~~~~~~~~~~~~~~~ 
INCLUDE/cb.h:42:1: note: candidate function [with P1 = const char *, P2 = const char *] 
INCLUDE/cbtypes.h:456:34: note: expanded from macro 'DECLARE_CBTYPE_FVV_AND_BUILDERS' <scratch space>:49:1: note: expanded from here 49 | 
makeWindowCallback INCLUDE/cb.h:42:1: note: candidate function [with P1 = const char *, P2 = const char *] 
INCLUDE/cbtypes.h:456:34: note: expanded from macro 'DECLARE_CBTYPE_FVV_AND_BUILDERS' <scratch space>:49:1: note: expanded from here 49 | makeWindowCallback

Similar errors occur for makeRootCallback in AW_names_admin.cxx:137, and for makeWindowCallback in probe_design.cxx (multiple call sites), rootAsWin.h:50, SaiProbeVisualization?.cxx:765, and MP_Window.cxx.

Root cause (traced in source):

In SL/CB/cbtypes.h, the macro CBTYPE_FVV_BUILDER_NP12 (and the analogous CBTYPE_VV_BUILDER_NP12) generates two overloads of the builder function for each parameter — one using the parameter type P1 as-is, and one using CONST_PARAM_T(P1):

CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,P1,P2);
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,P1,CONST_PARAM_T(P2));
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,CONST_PARAM_T(P1),P2);
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,CONST_PARAM_T(P1),CONST_PARAM_T(P2))

CONST_PARAM_T expands to ConstParamT<T>::Type. For pointer types, the specialization is:

template<typename T>
struct ConstParamT<T*> {
    typedef typename TypeOp<T>::ConstT *Type;
};

This takes the pointee type T and adds const to it. The problem: when T is already const-qualified — which is the case for all of ARB's AWAR name constants, typed as const char * — adding const to an already-const type is a no-op. So for P1 = const char*, both the "plain" builder overload and the "CONST_PARAM_T" builder overload end up with the exact same generated signature (const char*, const char*), i.e. two textually identical function template overloads are declared.

Apparently older Clang versions silently tolerated or merged this redundancy. Clang 21 now (correctly, per the standard) flags this as a genuine ambiguous overload, since there are two indistinguishable candidate templates.

This affects any callback type declared via DECLARE_CBTYPE_FVV_AND_BUILDERS / DECLARE_CBTYPE_VV_AND_BUILDERS (e.g. makeWindowCallback, makeRootCallback, makeTimedCallback, makeCreateWindowCallback) whenever it's invoked with const-qualified pointer parameters (most commonly const char* AWAR names) for both bound parameters.

Suggested fix direction:

A robust fix likely needs to avoid instantiating the "CONST_PARAM_T" overload when it would be identical to the plain P1/P2 overload — e.g. via a SFINAE/type-trait check (something like enable_if< !is_same<P1, CONST_PARAM_T(P1)>::value >) gating the redundant overload(s) in CBTYPE_FVV_BUILDER_P1P2 / CBTYPE_VV_BUILDER_P1P2. I have not attempted this patch myself, since I don't have access to ARB's test infrastructure to validate it doesn't break other instantiations of this macro (used across several callback types with different parameter shapes).

Additional notes:

This reproduces both on native Apple Silicon (arm64) and under Rosetta (x86_64) — it is not architecture-specific, purely a Clang-version issue. Already reported on the arb-project/homebrew-arb GitHub repo, issue #35, approximately 3 weeks ago, without a response — filing here as well since that may not be actively monitored. Happy to test a candidate patch against this exact build environment if one is proposed.

Change History (6)

comment:1 Changed 3 weeks ago by westram

  • Component changed from no idea to global
  • Description modified (diff)
  • Owner changed from devel to westram
  • Priority changed from normal to major
  • Status changed from new to accepted
  • Version set to SVN

Thank you for the bug report.

comment:2 Changed 3 weeks ago by westram

  • Status changed from accepted to _started

Jan had already submitted (an OpenCode generated) patch for this issue last monday.

comment:3 Changed 3 weeks ago by westram

[19974] basically fixed the problem. see ARB head build #1320

comment:4 Changed 3 weeks ago by westram

Building with unittests fails when using clang ≥ 20.1.0
Code to reproduce behavior: https://godbolt.org/z/jnrjchPbx
The code basically is an excerpt of the relevant parts from the preprocessor output of this revision of cb.cxx

comment:5 Changed 3 days ago by westram

  • builds w/o unittests succeeded until [19976], but only at the cost of accidentally sabotaging const correctness of callback interface.
  • [19983] (and probably already [19978]) fail again.

https://godbolt.org/z/Kh1er6vda contains code to track down the problem.

Last edited 2 days ago by westram (previous) (diff)

comment:6 Changed 41 hours ago by westram

[19985] fixed ambiguities for ARB head build #1338

Note: See TracTickets for help on using tickets.