[cfe-dev] [AST] Function redeclaration: parameter decl isn't redecl of same parameter of redecl'd function

David Rector via cfe-dev cfe-dev at lists.llvm.org
Mon Aug 17 10:58:52 PDT 2020


> On Aug 17, 2020, at 12:01 PM, Whisperity via cfe-dev <cfe-dev at lists.llvm.org> wrote:
> 
> Hey!
> 
> Suppose we have a rather trivial situation with a function prototype, a usage, and then later a definition:
> 
> int foo(int x);
> 
> void bar() {
>   foo(0);
> }
> 
> int foo(int x) { return x * 2; }
> 
> void baz() {
>   foo(1);
> }
> The following AST results:
> 
> |-FunctionDecl 0x55ae46421ca8 <a.cpp:1:1, col:14> col:5 used foo 'int (int)'
> | `-ParmVarDecl 0x55ae46421bd0 <col:9, col:13> col:13 x 'int'
> |-FunctionDecl 0x55ae46421df0 <line:2:1, col:23> col:6 bar 'void ()'
> | `-CompoundStmt 0x55ae46421f90 <col:12, col:23>
> |   `-CallExpr 0x55ae46421f68 <col:16, col:21> 'int'
> |     |-ImplicitCastExpr 0x55ae46421f50 <col:16> 'int (*)(int)' <FunctionToPointerDecay>
> |     | `-DeclRefExpr 0x55ae46421ef8 <col:16> 'int (int)' lvalue Function 0x55ae46421ca8 'foo' 'int (int)'
> |     `-IntegerLiteral 0x55ae46421ed8 <col:20> 'int' 0
> |-FunctionDecl 0x55ae46422058 prev 0x55ae46421ca8 <line:3:1, col:32> col:5 used foo 'int (int)'
> | |-ParmVarDecl 0x55ae46421fc0 <col:9, col:13> col:13 used x 'int'
> | `-CompoundStmt 0x55ae46422188 <col:16, col:32>
> |   `-ReturnStmt 0x55ae46422178 <col:18, col:29>
> |     `-BinaryOperator 0x55ae46422158 <col:25, col:29> 'int' '*'
> |       |-ImplicitCastExpr 0x55ae46422140 <col:25> 'int' <LValueToRValue>
> |       | `-DeclRefExpr 0x55ae46422100 <col:25> 'int' lvalue ParmVar 0x55ae46421fc0 'x' 'int'
> |       `-IntegerLiteral 0x55ae46422120 <col:29> 'int' 2
> `-FunctionDecl 0x55ae464221c0 <line:4:1, col:21> col:6 baz 'void ()'
>   `-CompoundStmt 0x55ae46422328 <col:12, col:21>
>     `-CallExpr 0x55ae46422300 <col:14, col:19> 'int'
>       |-ImplicitCastExpr 0x55ae464222e8 <col:14> 'int (*)(int)' <FunctionToPointerDecay>
>       | `-DeclRefExpr 0x55ae464222c8 <col:14> 'int (int)' lvalue Function 0x55ae46422058 'foo' 'int (int)'
>       `-IntegerLiteral 0x55ae464222a8 <col:18> 'int' 1
> The FunctionDecl knows that it is a redeclaration of a previous Decl (namely, the prototype). However, the two ParmVarDecls for int x do not have this relationship: PVD->getCanonicalDecl() == PVD holds for both instances, with no connection between. PVD->redecls() == {PVD}, too.
> What is more interesting, is that querying the parameter to which the CallExpr gives the argument to, by iterating the number of arguments and doing cast<FunctionDecl>(CE->getCalledDecl())->getParamDecl(0), we will get two separate ParmVarDecl instances, due to how the call before the definition of foo() binds the prototype (and gives us the prototype’s ParmVarDecl) but the call site after the called function has been defined bind the definition.
> 
> Is this an intended behaviour?
> Why isn’t the two ParmVarDecls not linked into a redecl chain, considering they should mean the “same entity”, as it is the same parameter of a redecl’d function?
> I obviously mean once we are past overloads, past template instantiations, etc. No “magic” should be intervening.
> Or is it me who’s not grasping something from the language correctly?
> 
That redeclarations of functions can assign different names to their parameters is the most illuminating factor, to me.  It suggests ParmVarDecls really are private to their parent FunctionDecl, and should not be linked to anything outside it — even to another redeclaration of that function.

Indeed, ParmVarDecls do not matter in any function declaration except a definition; only the parameter types matter, and they are enclosed in the function type.  In other words, ParmVarDecls seem to be unnecessary, semantically, in every declaration of a function except its definition.  In non-defined functions, their purpose is only to help record the name a user assigned to that slot, purely as syntactic sugar. 

Since there need not anything in common between ParmVarDecls of different redeclarations except their type — and even that is stored separately in the FunctionProtoType — I think it’s proper that each ParmVarDecl be considered completely enclosed from the world outside its particular function redeclaration.

- Dave

> Regards,
> W.
> 
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200817/773a8563/attachment.html>


More information about the cfe-dev mailing list