[clang] clang should have a warning to disallow re-externs (PR #109714)
https://github.com/jchcrsp updated https://github.com/llvm/llvm-project/pull/109714 >From 8f512e2a8ad110b1a74c4283f81d4e28555e7567 Mon Sep 17 00:00:00 2001 From: Jeffrey Crowell Date: Mon, 23 Sep 2024 16:17:32 -0400 Subject: [PATCH] clang should have a warning to disallow re-externs clang should have a warning to disallow re-externs from the main C translation unit for example, it would be helpful to warn programmers in this situation ```c // file1.c extern int func(int a, int b); int some_func() { func(1,2); } ``` ```c // file2.c int func(int a, int b, char *c, int d) { // function body } ``` --- clang/include/clang/Basic/DiagnosticGroups.td | 3 ++ .../clang/Basic/DiagnosticSemaKinds.td| 6 clang/include/clang/Sema/Sema.h | 9 + clang/lib/Sema/Sema.cpp | 2 ++ clang/lib/Sema/SemaDecl.cpp | 34 +++ .../Sema/warn-extern-func-not-in-header.c | 13 +++ 6 files changed, 67 insertions(+) create mode 100644 clang/test/Sema/warn-extern-func-not-in-header.c diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 7d81bdf827ea0c..9e8bd587094423 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1582,3 +1582,6 @@ def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; // Warnings about using the non-standard extension having an explicit specialization // with a storage class specifier. def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-storage-class">; + +// Warnings about extern functions not in header files. +def ExternalDeclaration : DiagGroup<"external-declaration">; \ No newline at end of file diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e4e04bff8b5120..16529dab1e245d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12614,4 +12614,10 @@ def err_acc_loop_spec_conflict // AMDGCN builtins diagnostics def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">; def note_amdgcn_global_load_lds_size_valid_value : Note<"size must be 1, 2, or 4">; + +// SemaExternWarning diagnostics +def warn_extern_func_not_in_header : Warning< + "extern function '%0' declared in main file '%1' instead of a header">, + InGroup, DefaultIgnore; + } // end of sema component. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e1c3a99cfa167e..76a9f4c84f47f7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4390,6 +4390,15 @@ class Sema final : public SemaBase { // linkage or not. static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); + ///@} + /// \name CheckExternFunction + ///@{ +public: + void CheckExternDecl(Decl *D); + void CheckDeferredExternDecls(); + +private: + std::vector ExternFuncDecls; ///@} // diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 6d7a57d7b5a41a..4a4aefcd38e4c7 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1177,6 +1177,8 @@ void Sema::ActOnEndOfTranslationUnit() { if (PP.isCodeCompletionEnabled()) return; + CheckDeferredExternDecls(); + // Complete translation units and modules define vtables and perform implicit // instantiations. PCH files do not. if (TUKind != TU_Prefix) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 31bf50a32a83c3..e2dbf9521aec6c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6058,6 +6058,10 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { Dcl && Dcl->getDeclContext()->isFileContext()) Dcl->setTopLevelDeclInObjCContainer(); + if (Dcl) { +CheckExternDecl(Dcl); + } + if (!Bases.empty()) OpenMP().ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases); @@ -20354,3 +20358,33 @@ bool Sema::diagnoseConflictingFunctionEffect( return false; } + +void Sema::CheckExternDecl(Decl *D) { + if (FunctionDecl *FD = dyn_cast(D)) { +SourceLocation Loc = FD->getLocation(); +SourceManager &SM = Context.getSourceManager(); + +// Only consider extern function declarations (not definitions) in the main +// file +if (FD->isExternC() && !FD->isImplicit() && !FD->getBuiltinID() && +!FD->hasBody() && !FD->isThisDeclarationADefinition() && +FD->isFirstDecl() && SM.isInMainFile(Loc)) { + // Defer the warning check until the end of the translation unit + ExternFuncDecls.push_back(FD); +} + } +} + +void Sema::CheckDeferredExternDecls() { + SourceManager &SM = Context.getSourceManager(); + for (FunctionDecl *FD : ExternFuncDecls) { +// Check if there's a definition in the same fi
[clang] clang should have a warning to disallow re-externs (PR #109714)
jchcrsp wrote: Ping fixed merge conflict https://github.com/llvm/llvm-project/pull/109714 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] clang should have a warning to disallow re-externs (PR #109714)
https://github.com/jchcrsp created https://github.com/llvm/llvm-project/pull/109714 clang should have a warning to disallow re-externs from the main C translation unit for example, it would be helpful to warn programmers in this situation ```c // file1.c extern int func(int a, int b); int some_func() { func(1,2); } ``` ```c // file2.c int func(int a, int b, char *c, int d) { // function body } ``` >From 8f512e2a8ad110b1a74c4283f81d4e28555e7567 Mon Sep 17 00:00:00 2001 From: Jeffrey Crowell Date: Mon, 23 Sep 2024 16:17:32 -0400 Subject: [PATCH] clang should have a warning to disallow re-externs clang should have a warning to disallow re-externs from the main C translation unit for example, it would be helpful to warn programmers in this situation ```c // file1.c extern int func(int a, int b); int some_func() { func(1,2); } ``` ```c // file2.c int func(int a, int b, char *c, int d) { // function body } ``` --- clang/include/clang/Basic/DiagnosticGroups.td | 3 ++ .../clang/Basic/DiagnosticSemaKinds.td| 6 clang/include/clang/Sema/Sema.h | 9 + clang/lib/Sema/Sema.cpp | 2 ++ clang/lib/Sema/SemaDecl.cpp | 34 +++ .../Sema/warn-extern-func-not-in-header.c | 13 +++ 6 files changed, 67 insertions(+) create mode 100644 clang/test/Sema/warn-extern-func-not-in-header.c diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 7d81bdf827ea0c..9e8bd587094423 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1582,3 +1582,6 @@ def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; // Warnings about using the non-standard extension having an explicit specialization // with a storage class specifier. def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-storage-class">; + +// Warnings about extern functions not in header files. +def ExternalDeclaration : DiagGroup<"external-declaration">; \ No newline at end of file diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e4e04bff8b5120..16529dab1e245d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12614,4 +12614,10 @@ def err_acc_loop_spec_conflict // AMDGCN builtins diagnostics def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">; def note_amdgcn_global_load_lds_size_valid_value : Note<"size must be 1, 2, or 4">; + +// SemaExternWarning diagnostics +def warn_extern_func_not_in_header : Warning< + "extern function '%0' declared in main file '%1' instead of a header">, + InGroup, DefaultIgnore; + } // end of sema component. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e1c3a99cfa167e..76a9f4c84f47f7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4390,6 +4390,15 @@ class Sema final : public SemaBase { // linkage or not. static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); + ///@} + /// \name CheckExternFunction + ///@{ +public: + void CheckExternDecl(Decl *D); + void CheckDeferredExternDecls(); + +private: + std::vector ExternFuncDecls; ///@} // diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 6d7a57d7b5a41a..4a4aefcd38e4c7 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1177,6 +1177,8 @@ void Sema::ActOnEndOfTranslationUnit() { if (PP.isCodeCompletionEnabled()) return; + CheckDeferredExternDecls(); + // Complete translation units and modules define vtables and perform implicit // instantiations. PCH files do not. if (TUKind != TU_Prefix) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 31bf50a32a83c3..e2dbf9521aec6c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6058,6 +6058,10 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { Dcl && Dcl->getDeclContext()->isFileContext()) Dcl->setTopLevelDeclInObjCContainer(); + if (Dcl) { +CheckExternDecl(Dcl); + } + if (!Bases.empty()) OpenMP().ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases); @@ -20354,3 +20358,33 @@ bool Sema::diagnoseConflictingFunctionEffect( return false; } + +void Sema::CheckExternDecl(Decl *D) { + if (FunctionDecl *FD = dyn_cast(D)) { +SourceLocation Loc = FD->getLocation(); +SourceManager &SM = Context.getSourceManager(); + +// Only consider extern function declarations (not definitions) in the main +// file +if (FD->isExternC() && !FD->isImplicit() && !FD->getBuiltinID() && +!FD->hasBody() && !FD->isThisDeclarationADefinition() && +FD->isFirstDecl() && SM.isInMainFile(
[clang] clang should have a warning to disallow re-externs (PR #109714)
jchcrsp wrote: Ping https://github.com/llvm/llvm-project/pull/109714 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits