r373078 - [clang] [AST] Treat "inline gnu_inline" the same way as "extern inline gnu_inline" in C++ mode

Martin Storsjo via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 27 05:25:19 PDT 2019


Author: mstorsjo
Date: Fri Sep 27 05:25:19 2019
New Revision: 373078

URL: http://llvm.org/viewvc/llvm-project?rev=373078&view=rev
Log:
[clang] [AST] Treat "inline gnu_inline" the same way as "extern inline gnu_inline" in C++ mode

This matches how GCC handles it, see e.g. https://gcc.godbolt.org/z/HPplnl.
GCC documents the gnu_inline attribute with "In C++, this attribute does
not depend on extern in any way, but it still requires the inline keyword
to enable its special behavior."

The previous behaviour of gnu_inline in C++, without the extern
keyword, can be traced back to the original commit that added
support for gnu_inline, SVN r69045.

Differential Revision: https://reviews.llvm.org/D67414

Added:
    cfe/trunk/test/SemaCXX/gnu_inline.cpp
Modified:
    cfe/trunk/docs/ReleaseNotes.rst
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/CodeGen/inline.c
    cfe/trunk/test/SemaCUDA/gnu-inline.cu
    cfe/trunk/test/SemaCXX/undefined-inline.cpp

Modified: cfe/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/docs/ReleaseNotes.rst (original)
+++ cfe/trunk/docs/ReleaseNotes.rst Fri Sep 27 05:25:19 2019
@@ -128,7 +128,10 @@ C11 Feature Support
 C++ Language Changes in Clang
 -----------------------------
 
-- ...
+- The behaviour of the `gnu_inline` attribute now matches GCC, for cases
+  where used without the `extern` keyword. As this is a change compared to
+  how it behaved in previous Clang versions, a warning is emitted for this
+  combination.
 
 C++1z Feature Support
 ^^^^^^^^^^^^^^^^^^^^^

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 27 05:25:19 2019
@@ -3008,6 +3008,10 @@ def warn_gnu_inline_attribute_requires_i
   "'gnu_inline' attribute requires function to be marked 'inline',"
   " attribute ignored">,
   InGroup<IgnoredAttributes>;
+def warn_gnu_inline_cplusplus_without_extern : Warning<
+  "'gnu_inline' attribute without 'extern' in C++ treated as externally"
+  " available, this changed in Clang 10">,
+  InGroup<DiagGroup<"gnu-inline-cpp-without-extern">>;
 def err_attribute_vecreturn_only_vector_member : Error<
   "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
 def err_attribute_vecreturn_only_pod_record : Error<

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Sep 27 05:25:19 2019
@@ -3261,6 +3261,9 @@ bool FunctionDecl::doesDeclarationForceE
       return true;
   }
 
+  if (Context.getLangOpts().CPlusPlus)
+    return false;
+
   if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
     // With GNU inlining, a declaration with 'inline' but not 'extern', forces
     // an externally visible definition.
@@ -3289,9 +3292,6 @@ bool FunctionDecl::doesDeclarationForceE
     return FoundBody;
   }
 
-  if (Context.getLangOpts().CPlusPlus)
-    return false;
-
   // C99 6.7.4p6:
   //   [...] If all of the file scope declarations for a function in a
   //   translation unit include the inline function specifier without extern,
@@ -3371,6 +3371,8 @@ bool FunctionDecl::isInlineDefinitionExt
     // If it's not the case that both 'inline' and 'extern' are
     // specified on the definition, then this inline definition is
     // externally visible.
+    if (Context.getLangOpts().CPlusPlus)
+      return false;
     if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
       return true;
 

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Sep 27 05:25:19 2019
@@ -4255,6 +4255,9 @@ static void handleGNUInlineAttr(Sema &S,
     return;
   }
 
+  if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern)
+    S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern);
+
   D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL));
 }
 

Modified: cfe/trunk/test/CodeGen/inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/inline.c?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/inline.c (original)
+++ cfe/trunk/test/CodeGen/inline.c Fri Sep 27 05:25:19 2019
@@ -52,7 +52,7 @@
 // CHECK3-LABEL: define i32 @_Z3barv()
 // CHECK3-LABEL: define linkonce_odr i32 @_Z3foov()
 // CHECK3-NOT: unreferenced
-// CHECK3-LABEL: define void @_Z10gnu_inlinev()
+// CHECK3-LABEL: define available_externally void @_Z10gnu_inlinev()
 // CHECK3-LABEL: define available_externally void @_Z13gnu_ei_inlinev()
 // CHECK3-NOT: @_Z5testCv
 // CHECK3-LABEL: define linkonce_odr i32 @_Z2eiv()
@@ -85,6 +85,7 @@ __inline void unreferenced1() {}
 extern __inline void unreferenced2() {}
 
 __inline __attribute((__gnu_inline__)) void gnu_inline() {}
+void (*P1)() = gnu_inline;
 
 // PR3988
 extern __inline __attribute__((gnu_inline)) void gnu_ei_inline() {}

Modified: cfe/trunk/test/SemaCUDA/gnu-inline.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/gnu-inline.cu?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/test/SemaCUDA/gnu-inline.cu (original)
+++ cfe/trunk/test/SemaCUDA/gnu-inline.cu Fri Sep 27 05:25:19 2019
@@ -7,4 +7,4 @@
 // Check that we can handle gnu_inline functions when compiling in CUDA mode.
 
 void foo();
-inline __attribute__((gnu_inline)) void bar() { foo(); }
+extern inline __attribute__((gnu_inline)) void bar() { foo(); }

Added: cfe/trunk/test/SemaCXX/gnu_inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/gnu_inline.cpp?rev=373078&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/gnu_inline.cpp (added)
+++ cfe/trunk/test/SemaCXX/gnu_inline.cpp Fri Sep 27 05:25:19 2019
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+extern inline
+__attribute__((__gnu_inline__))
+void gnu_inline1() {}
+
+inline
+__attribute__((__gnu_inline__)) // expected-warning {{'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10}}
+void gnu_inline2() {}

Modified: cfe/trunk/test/SemaCXX/undefined-inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/undefined-inline.cpp?rev=373078&r1=373077&r2=373078&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/undefined-inline.cpp (original)
+++ cfe/trunk/test/SemaCXX/undefined-inline.cpp Fri Sep 27 05:25:19 2019
@@ -40,20 +40,20 @@ namespace test7 {
 }
 
 namespace test8 {
-  inline void foo() __attribute__((gnu_inline));
+  inline void foo() __attribute__((gnu_inline)); // expected-warning {{'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10}}
   void test() { foo(); }
 }
 
 namespace test9 {
   void foo();
   void test() { foo(); }
-  inline void foo() __attribute__((gnu_inline));
+  inline void foo() __attribute__((gnu_inline)); // expected-warning {{'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10}}
 }
 
 namespace test10 {
   inline void foo();
   void test() { foo(); }
-  inline void foo() __attribute__((gnu_inline));
+  inline void foo() __attribute__((gnu_inline)); // expected-warning {{'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10}}
 }
 
 namespace test11 {




More information about the cfe-commits mailing list