[PATCH] cc1: Add support for __func__ variable

From: Roberto E. Vargas Caballero <k0ga_at_shike2.com>
Date: Thu, 23 Mar 2023 18:00:53 +0100

__func__ is a variable with the name of the current function
and only can be used inside of functions and we take the
decision of giving an error when it is redefined in any way,
that is a valid behaviour since the standard defines this
situation as undefined behaviour.
---
 src/cmd/cc/cc1/decl.c          |  5 +++++
 src/cmd/cc/cc1/expr.c          | 21 ++++++++++++++++++++-
 tests/cc/error/0036-func.c     | 13 +++++++++++++
 tests/cc/error/scc-tests.lst   |  1 +
 tests/cc/execute/0225-func.c   | 12 ++++++++++++
 tests/cc/execute/scc-tests.lst |  1 +
 6 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 tests/cc/error/0036-func.c
 create mode 100644 tests/cc/execute/0225-func.c
diff --git a/src/cmd/cc/cc1/decl.c b/src/cmd/cc/cc1/decl.c
index d123cdc8..058a9eb7 100644
--- a/src/cmd/cc/cc1/decl.c
+++ b/src/cmd/cc/cc1/decl.c
_at_@ -272,6 +272,9 @@ identifier(struct decl *dcl)
 		}
 	}
 
+	if (strcmp(name, "__func__") == 0)
+		errorp("__func__ is a reserved variable name");
+
 	if (sym->flags & SDECLARED) {
 		sym = redcl(dcl->sym, tp, sclass);
 	} else {
_at_@ -363,6 +366,8 @@ parameter(struct decl *dcl)
 			       sym->name);
 			return NULL;
 		}
+		if (strcmp(name, "__func__") == 0)
+			errorp("__func__ is a reserved variable name");
 		sym->flags |= SDECLARED;
 	}
 
diff --git a/src/cmd/cc/cc1/expr.c b/src/cmd/cc/cc1/expr.c
index 75edb4b4..1d33c289 100644
--- a/src/cmd/cc/cc1/expr.c
+++ b/src/cmd/cc/cc1/expr.c
_at_@ -674,6 +674,23 @@ adjstrings(Symbol *sym)
 	return sym;
 }
 
+static Node *
+funcsym(Symbol *sym)
+{
+	char *s;
+	Node *np;
+
+	sym = install(sym->ns, sym);
+	s = curfun->name;
+	np = constnode(newstring(s, strlen(s)+1));
+	sym->type = np->type;
+	sym->flags |= SHASINIT | SLOCAL | SUSED;
+	emit(ODECL, sym);
+	emit(OINIT, np);
+
+	return varnode(sym);
+}
+
 /*************************************************************
  * grammar functions                                         *
  *************************************************************/
_at_@ -721,10 +738,12 @@ primary(void)
 			np = varnode(sym);
 		} else if (namespace == NS_CPP) {
 			np = constnode(zero);
+		} else if (!strcmp(yytext, "__func__") && curctx > PARAMCTX) {
+			np = funcsym(sym);
 		} else {
 			errorp("'%s' undeclared", yytext);
 			sym->type = inttype;
-			sym = install(sym->ns, yylval.sym);
+			sym = install(sym->ns, sym);
 			sym->flags |= SUSED;
 			np = varnode(sym);
 		}
diff --git a/tests/cc/error/0036-func.c b/tests/cc/error/0036-func.c
new file mode 100644
index 00000000..eccb744c
--- /dev/null
+++ b/tests/cc/error/0036-func.c
_at_@ -0,0 +1,13 @@
+/*
+PATTERN:
+0036-func.c:8: error: __func__ is a reserved variable name
+0036-func.c:10: error: __func__ is a reserved variable name
+0036-func.c:13: warning: '__func__' defined but not used
+.
+*/
+int __func__;
+
+int foo(int __func__)
+{
+	return 0;
+}
diff --git a/tests/cc/error/scc-tests.lst b/tests/cc/error/scc-tests.lst
index d61a3e18..7dbe4e71 100644
--- a/tests/cc/error/scc-tests.lst
+++ b/tests/cc/error/scc-tests.lst
_at_@ -33,3 +33,4 @@
 0033-character.c
 0034-eof.c
 0035-cpp.c
+0036-func.c
diff --git a/tests/cc/execute/0225-func.c b/tests/cc/execute/0225-func.c
new file mode 100644
index 00000000..823866d6
--- /dev/null
+++ b/tests/cc/execute/0225-func.c
_at_@ -0,0 +1,12 @@
+int
+main(void)
+{
+	char *p = __func__;
+	int i;
+
+	for (i = 0; i < sizeof(__func__); i++) {
+		if (p[i] != "main"[i])
+			return 1;
+	}
+	return 0;
+}
diff --git a/tests/cc/execute/scc-tests.lst b/tests/cc/execute/scc-tests.lst
index 4eea22e9..6f5080e2 100644
--- a/tests/cc/execute/scc-tests.lst
+++ b/tests/cc/execute/scc-tests.lst
_at_@ -215,3 +215,4 @@
 0222-ifdef.c
 0223-macro.c
 0224-macro.c
+0225-func.c
-- 
2.40.0
--
To unsubscribe send a mail to scc-dev+unsubscribe_at_simple-cc.org
Received on Mon 17 Sep 2001 - 00:00:00 CEST

This archive was generated by hypermail 2.3.0 : Fri 21 Apr 2023 - 16:44:23 CEST