diff options
-rw-r--r-- | clang/docs/ReleaseNotes.rst | 5 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGen/inline.c | 3 | ||||
-rw-r--r-- | clang/test/SemaCUDA/gnu-inline.cu | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/gnu_inline.cpp | 9 | ||||
-rw-r--r-- | clang/test/SemaCXX/undefined-inline.cpp | 6 |
8 files changed, 31 insertions, 9 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5dbc4a0415c..91ae3071ff8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c2cef944b6e..adc658bb294 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3008,6 +3008,10 @@ def warn_gnu_inline_attribute_requires_inline : Warning< "'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< diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index e95338138fe..19a012b332d 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3261,6 +3261,9 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { 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::doesDeclarationForceExternallyVisibleDefinition() const { 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::isInlineDefinitionExternallyVisible() const { // 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; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b69cb5d8433..d31b48c122f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4255,6 +4255,9 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { 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)); } diff --git a/clang/test/CodeGen/inline.c b/clang/test/CodeGen/inline.c index ea6e9d76494..b511ece2813 100644 --- a/clang/test/CodeGen/inline.c +++ b/clang/test/CodeGen/inline.c @@ -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() {} diff --git a/clang/test/SemaCUDA/gnu-inline.cu b/clang/test/SemaCUDA/gnu-inline.cu index 0ed543326be..e383082f2a7 100644 --- a/clang/test/SemaCUDA/gnu-inline.cu +++ b/clang/test/SemaCUDA/gnu-inline.cu @@ -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(); } diff --git a/clang/test/SemaCXX/gnu_inline.cpp b/clang/test/SemaCXX/gnu_inline.cpp new file mode 100644 index 00000000000..43a4bae48e9 --- /dev/null +++ b/clang/test/SemaCXX/gnu_inline.cpp @@ -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() {} diff --git a/clang/test/SemaCXX/undefined-inline.cpp b/clang/test/SemaCXX/undefined-inline.cpp index feb12f4552c..21c6b5de79d 100644 --- a/clang/test/SemaCXX/undefined-inline.cpp +++ b/clang/test/SemaCXX/undefined-inline.cpp @@ -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 { |