[clang] [clang][ThreadSafety] Instantiate a parameter's attribute naming a later parameter (PR #232784)
Jameson Nash via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 17:38:11 PDT 2026
================
@@ -5493,23 +5520,25 @@ TypeSourceInfo *TemplateDeclInstantiator::SubstFunctionType(
// the function parameters themselves.
const FunctionProtoType *OldProto =
cast<FunctionProtoType>(OldProtoLoc.getType());
- for (unsigned i = 0, i_end = OldProtoLoc.getNumParams(); i != i_end;
- ++i) {
- ParmVarDecl *OldParam = OldProtoLoc.getParam(i);
- if (!OldParam) {
- Params.push_back(SemaRef.BuildParmVarDeclForTypedef(
- D, D->getLocation(), OldProto->getParamType(i)));
- continue;
- }
-
- ParmVarDecl *Parm = SemaRef.SubstParmVarDecl(
- OldParam, TemplateArgs, /*indexAdjustment=*/0,
- /*NumExpansions=*/std::nullopt,
- /*ExpectParameterPack=*/false, EvaluateConstraints);
- if (!Parm)
- return nullptr;
- Params.push_back(Parm);
- }
+ SmallVector<QualType, 4> ParamTypes;
+ Sema::ExtParameterInfoBuilder ExtParamInfos;
+ if (SemaRef.SubstParmTypes(D->getLocation(), OldProtoLoc.getParams(),
+ nullptr, TemplateArgs, ParamTypes, &Params,
+ ExtParamInfos, OldProto->param_type_begin(),
+ EvaluateConstraints))
+ return nullptr;
+ // Declare a parameter that was only a type in the prototype. A function
+ // declared through a typedef with an attribute that rewrites the
+ // function type in place, such as noreturn, gets a prototype whose
+ // parameters have no ParmVarDecl, so no attribute of the typedef's
+ // parameters reaches it; see TypeSpecLocFiller in SemaType.
+ // FIXME: Keep the typedef's parameters there instead. The dependent
+ // branch above returns null for such a prototype, dropping the member.
----------------
vtjnash wrote:
That's certainly a possible cause, though I think noreturn might affect overloads? and so we happen to know that Clang has to crash because of that, if it ends up instantiating a noreturn function inferred as a different overload, since this "no behavior change goal" is in contradiction to the part of the C++ spec that requires each distinguishable type must have a different mangling (so that different typedef don't attempt to generate into the same llvm function by name). This is also likely one of the hardest problems with getting TSA to be a type attribute. Claude wrote about that particular problem with noreturn that it encountered why making the typedef-capability experiment. I've mentioned it before, but it's specifically the "ABI hazard" it mentioned in the later commits it made:
https://github.com/vtjnash/llvm-project/blob/jn/tsa-typedef-capability/clang/docs/ThreadSafetyTypeCapabilities-Design.md#the-canonical-choice-creates-an-abi-hazard-so-the-policy-is-explicit
https://github.com/llvm/llvm-project/pull/232784
More information about the cfe-commits
mailing list