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

Whisperity via cfe-dev cfe-dev at lists.llvm.org
Mon Aug 17 09:01:34 PDT 2020


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?

Regards,
W.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200817/d96fd9dd/attachment-0001.html>


More information about the cfe-dev mailing list