aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land.
LGTM with a commenting request. ================ Comment at: test/clang-tidy/google-objc-function-naming.m:5-8 +static void TestImplicitlyDefinedFunction(int a) { + printf("%d", a); +} + ---------------- stephanemoore wrote: > 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 ๐ค Well that certainly is neat; I didn't know that! Can you add some comments above the function call to explain that to the next person reading the test? Repository: rCTE Clang Tools Extra CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57207/new/ https://reviews.llvm.org/D57207 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits