]> granicus.if.org Git - clang/commitdiff
Allow internal decls in inline functions if the function is in the main file.
authorJordan Rose <jordan_rose@apple.com>
Mon, 18 Jun 2012 17:49:58 +0000 (17:49 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 18 Jun 2012 17:49:58 +0000 (17:49 +0000)
This handles the very common case of people writing inline functions in their
main source files and not tagging them as inline. These cases should still
behave as the user intended. (The diagnostic is still emitted as an extension.)

I'm reworking this code anyway to account for C++'s equivalent restriction in
[basic.def.odr]p6, but this should get some bots back to green.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158666 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/inline.c

index 86c1f84668cc8a0e70e15bcdd0b515322767281b..3b7e0522687ebf7737d0b824308f242e4b85fa0f 100644 (file)
@@ -3000,6 +3000,10 @@ def warn_internal_in_extern_inline : ExtWarn<
   "%select{function|variable}0 %1 has internal linkage but is used in an "
   "inline %select{function|method}2 with external linkage">,
   InGroup<DiagGroup<"internal-linkage-in-inline"> >;
+def ext_internal_in_extern_inline : Extension<
+  "%select{function|variable}0 %1 has internal linkage but is used in an "
+  "inline %select{function|method}2 with external linkage">,
+  InGroup<DiagGroup<"internal-linkage-in-inline"> >;
 def note_internal_decl_declared_here : Note<
   "%0 declared here">;
 def note_convert_inline_to_static : Note<
index ae3a6369e19df5f59fe4b9f0816d82525990044c..d9950949ea85d9303892ccf044b21a6621fc53da 100644 (file)
@@ -194,7 +194,13 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
     if (FunctionDecl *Current = getCurFunctionDecl()) {
       if (Current->isInlined() && Current->getLinkage() > InternalLinkage) {
         if (D->getLinkage() == InternalLinkage) {
-          Diag(Loc, diag::warn_internal_in_extern_inline)
+          // We won't warn by default if the inline function is in the main
+          // source file; in these cases it is almost certain that the inlining
+          // will only occur in this file, even if there is an external
+          // declaration as well.
+          bool IsFromMainFile = getSourceManager().isFromMainFile(Loc);
+          Diag(Loc, IsFromMainFile ? diag::ext_internal_in_extern_inline
+                                   : diag::warn_internal_in_extern_inline)
             << !isa<FunctionDecl>(D) << D << isa<CXXMethodDecl>(Current);
 
           // If the user didn't explicitly specify a storage class,
index 37dba8c38218c54e16f50848500e5b0a12c92bfe..23eedd6b2265d9e7073fdcc3ec6920df178499fd 100644 (file)
@@ -1,14 +1,13 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-// Check that we don't allow illegal uses of inline
-inline int a; // expected-error{{'inline' can only appear on functions}}
-typedef inline int b; // expected-error{{'inline' can only appear on functions}}
-int d(inline int a); // expected-error{{'inline' can only appear on functions}}
-
+#if defined(INCLUDE)
+// -------
+// This section acts like a header file.
+// -------
 
 // Check the use of static variables in non-static inline functions.
-static int staticVar; // expected-note 2 {{'staticVar' declared here}}
-static int staticFunction(); // expected-note 2 {{'staticFunction' declared here}}
+static int staticVar; // expected-note + {{'staticVar' declared here}}
+static int staticFunction(); // expected-note + {{'staticFunction' declared here}}
 
 inline int useStatic () { // expected-note 2 {{use 'static' to give inline function 'useStatic' internal linkage}}
   staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline function with external linkage}}
@@ -24,3 +23,40 @@ static inline int useStaticFromStatic () {
   staticFunction(); // no-warning
   return staticVar; // no-warning
 }
+
+#else
+// -------
+// This is the main source file.
+// -------
+
+#define INCLUDE
+#include "inline.c"
+
+// Check that we don't allow illegal uses of inline
+inline int a; // expected-error{{'inline' can only appear on functions}}
+typedef inline int b; // expected-error{{'inline' can only appear on functions}}
+int d(inline int a); // expected-error{{'inline' can only appear on functions}}
+
+// Check that the warnings from the "header file" aren't on by default in
+// the main source file.
+
+inline int useStaticMain () {
+  staticFunction(); // no-warning
+  return staticVar; // no-warning
+}
+
+// Check that the warnings show up when explicitly requested.
+
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Winternal-linkage-in-inline"
+
+inline int useStaticAgain () { // expected-note 2 {{use 'static' to give inline function 'useStaticAgain' internal linkage}}
+  staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline function with external linkage}}
+  return staticVar; // expected-warning{{variable 'staticVar' has internal linkage but is used in an inline function with external linkage}}
+}
+
+#pragma clang diagnostic pop
+
+#endif
+
+