================
@@ -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.
----------------
aaronpuchert wrote:

> That's certainly a possible cause, though I think noreturn might affect 
> overloads?

I guess what's tricky about `__attribute__((noreturn))` is that it's a type 
attribute, whereas standard `_Noreturn` (C) and `[[noreturn]]` (C++) are 
declaration attributes:
```c++
[[noreturn]] void f();
_Noreturn void g();
__attribute__((noreturn)) void h();
```
produces
```
FunctionDecl f 'void ()' external-linkage
`-CXX11NoReturnAttr noreturn
FunctionDecl g 'void ()' external-linkage
`-C11NoReturnAttr
FunctionDecl h 'void () __attribute__((noreturn))' external-linkage
```
My guess is that this causes subtle issues in the handling of these attributes.

> This is also likely one of the hardest problems with getting TSA to be a type 
> attribute.

Yes, that's a problem. But static analysis attributes can be stripped on 
canonicalization, and even if we do that we still have better coverage than 
declaration attributes, and (I hope) in some cases a more straightforward 
implementation.

We don't ever want the attributes to affect mangling, because it shouldn't 
affect the ABI. I have been thinking in the past about instantiating "shadow" 
templates which are only used for static analysis and not for code generation, 
but it's a pipe dream for now and we have more pressing issues.

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

Reply via email to