[PATCH] D57207: [clang-tidy] Make google-objc-function-naming ignore implicit functions ๐Ÿ™ˆ

Stephane Moore via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 25 15:56:44 PST 2019


stephanemoore marked 2 inline comments as done.
stephanemoore added inline comments.


================
Comment at: clang-tidy/google/FunctionNamingCheck.cpp:96-97
 
   // Match function declarations that are not in system headers and are not
   // main.
   Finder->addMatcher(
----------------
aaron.ballman wrote:
> This comment is drifting more and more out of sync with the code.
Good catch; updated the comment.


================
Comment at: test/clang-tidy/google-objc-function-naming.m:5-8
+static void TestImplicitlyDefinedFunction(int a) {
+  printf("%d", a);
+}
+
----------------
aaron.ballman wrote:
> Excuse my ignorance, but I don't see what about this function definition is testing an implicitly-defined function. Doesn't the `#import` above bring in the declaration for `printf()`, while `TestImplicitlyDefinedFunction()` itself is explicitly defined?
**tl;dr**: Yes, we have an explicit function declaration but clang generates an implicit function declaration as well.

I found this surprising as well but the AST generated from this includes an implicit function declaration. Even though we have an explicit function declaration for `printf` from <stdio.h>, clang still generates an implicit declaration of `printf` ๐Ÿคจ Similar behavior occurs with other functions, e.g., `memset` and various C11 atomic functions.

I have been spelunking in search of the reason but I do not have a full understanding yet. I believe I have insight into the underlying mechanism though: the behavior seems linked to builtin functions (e.g., `printf` is declared as a builtin function [here](https://github.com/llvm/llvm-project/blob/2946cd7/clang/include/clang/Basic/Builtins.def#L889)). I have attached a small sample program and an associated AST dump below to demonstrate the behavior.

โง

```
$ cat /tmp/test.c
extern int printf(const char *format, ...);

int main(int argc, const char **argv) {
  printf("%d", argc);
  return 0;
}
```

```
$ clang -cc1 -ast-dump /tmp/test.c 
TranslationUnitDecl 0x561b9f7fe570 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x561b9f7feac0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x561b9f7fe7e0 '__int128'
|-TypedefDecl 0x561b9f7feb28 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x561b9f7fe800 'unsigned __int128'
|-TypedefDecl 0x561b9f7fedf8 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x561b9f7fec00 'struct __NSConstantString_tag'
|   `-Record 0x561b9f7feb78 '__NSConstantString_tag'
|-TypedefDecl 0x561b9f7fee90 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x561b9f7fee50 'char *'
|   `-BuiltinType 0x561b9f7fe600 'char'
|-TypedefDecl 0x561b9f7ff158 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x561b9f7ff100 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x561b9f7fef70 'struct __va_list_tag'
|     `-Record 0x561b9f7feee0 '__va_list_tag'
|-FunctionDecl 0x561b9f851860 </tmp/test.c:1:12> col:12 implicit used printf 'int (const char *, ...)' extern
| |-ParmVarDecl 0x561b9f8518f8 <<invalid sloc>> <invalid sloc> 'const char *'
| `-FormatAttr 0x561b9f851960 <col:12> Implicit printf 1 2
|-FunctionDecl 0x561b9f8519b8 prev 0x561b9f851860 <col:1, col:42> col:12 used printf 'int (const char *, ...)' extern
| |-ParmVarDecl 0x561b9f7ff1c0 <col:19, col:31> col:31 format 'const char *'
| `-FormatAttr 0x561b9f851a90 <col:12> Inherited printf 1 2
`-FunctionDecl 0x561b9f851c48 <line:3:1, line:6:1> line:3:5 main 'int (int, const char **)'
  |-ParmVarDecl 0x561b9f851ac8 <col:10, col:14> col:14 used argc 'int'
  |-ParmVarDecl 0x561b9f851b70 <col:20, col:33> col:33 argv 'const char **'
  `-CompoundStmt 0x561b9f851f08 <col:39, line:6:1>
    |-CallExpr 0x561b9f851e50 <line:4:3, col:20> 'int'
    | |-ImplicitCastExpr 0x561b9f851e38 <col:3> 'int (*)(const char *, ...)' <FunctionToPointerDecay>
    | | `-DeclRefExpr 0x561b9f851d58 <col:3> 'int (const char *, ...)' Function 0x561b9f8519b8 'printf' 'int (const char *, ...)'
    | |-ImplicitCastExpr 0x561b9f851ea0 <col:10> 'const char *' <BitCast>
    | | `-ImplicitCastExpr 0x561b9f851e88 <col:10> 'char *' <ArrayToPointerDecay>
    | |   `-StringLiteral 0x561b9f851db8 <col:10> 'char [3]' lvalue "%d"
    | `-ImplicitCastExpr 0x561b9f851eb8 <col:16> 'int' <LValueToRValue>
    |   `-DeclRefExpr 0x561b9f851de8 <col:16> 'int' lvalue ParmVar 0x561b9f851ac8 'argc' 'int'
    `-ReturnStmt 0x561b9f851ef0 <line:5:3, col:10>
      `-IntegerLiteral 0x561b9f851ed0 <col:10> 'int' 0
```

Note the presence of implicit and explicit declarations of `printf` in the AST dump ๐Ÿค”


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57207/new/

https://reviews.llvm.org/D57207





More information about the cfe-commits mailing list