]> granicus.if.org Git - clang/commitdiff
Make GNUInline consistent with whether we use traditional GNU inline semantics.
authorPeter Collingbourne <peter@pcc.me.uk>
Wed, 13 May 2015 22:07:22 +0000 (22:07 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Wed, 13 May 2015 22:07:22 +0000 (22:07 +0000)
Previously we were setting LangOptions::GNUInline (which controls whether we
use traditional GNU inline semantics) if the language did not have the C99
feature flag set. The trouble with this is that C++ family languages also
do not have that flag set, so we ended up setting this flag in C++ modes
(and working around it in a few places downstream by also checking CPlusPlus).

The fix is to check whether the C89 flag is set for the target language,
rather than whether the C99 flag is cleared. This also lets us remove most
CPlusPlus checks. We continue to test CPlusPlus when deciding whether to
pre-define the __GNUC_GNU_INLINE__ macro for consistency with GCC.

There is a change in semantics in two other places
where we weren't checking both CPlusPlus and GNUInline
(FunctionDecl::doesDeclarationForceExternallyVisibleDefinition and
FunctionDecl::isInlineDefinitionExternallyVisible), but this change seems to
put us back into line with GCC's semantics (test case: test/CodeGen/inline.c).

While at it, forbid -fgnu89-inline in C++ modes, as GCC doesn't support it,
it didn't have any effect before, and supporting it just makes things more
complicated.

Differential Revision: http://reviews.llvm.org/D9333

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

lib/Frontend/CompilerInvocation.cpp
lib/Frontend/InitPreprocessor.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
test/CodeGen/inline.c
test/Frontend/gnu-inline.c [new file with mode: 0644]

index 5e59800c5f7d06b37c5c21adad69bd3711d3ff80..d2514acd6def326a29c5a7dc333fe74643e61d87 100644 (file)
@@ -1236,7 +1236,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
   Opts.CPlusPlus1z = Std.isCPlusPlus1z();
   Opts.Digraphs = Std.hasDigraphs();
   Opts.GNUMode = Std.isGNUMode();
-  Opts.GNUInline = !Std.isC99();
+  Opts.GNUInline = Std.isC89();
   Opts.HexFloats = Std.hasHexFloats();
   Opts.ImplicitInt = Std.hasImplicitInt();
 
@@ -1419,8 +1419,13 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
         (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
   }
     
-  if (Args.hasArg(OPT_fgnu89_inline))
-    Opts.GNUInline = 1;
+  if (Args.hasArg(OPT_fgnu89_inline)) {
+    if (Opts.CPlusPlus)
+      Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline"
+                                                            << "C++/ObjC++";
+    else
+      Opts.GNUInline = 1;
+  }
 
   if (Args.hasArg(OPT_fapple_kext)) {
     if (!Opts.CPlusPlus)
index d9ae3ba81dd14489da65f9b8177d0495d76d94f2..0d97709607a13af62e6b3cce2d08100338ded01b 100644 (file)
@@ -790,7 +790,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
     Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
 
   if (!LangOpts.MSVCCompat) {
-    if (LangOpts.GNUInline)
+    if (LangOpts.GNUInline || LangOpts.CPlusPlus)
       Builder.defineMacro("__GNUC_GNU_INLINE__");
     else
       Builder.defineMacro("__GNUC_STDC_INLINE__");
index ac8f57698b3cd14d871cfe8c411aea8e367d2ce8..8be7286f66fadb273a63af3738924cb335d84a70 100644 (file)
@@ -2710,7 +2710,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
   // UndefinedButUsed.
   if (!Old->isInlined() && New->isInlined() &&
       !New->hasAttr<GNUInlineAttr>() &&
-      (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) &&
+      !getLangOpts().GNUInline &&
       Old->isUsed(false) &&
       !Old->isDefined() && !New->isThisDeclarationADefinition())
     UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
@@ -10616,7 +10616,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
       if (!FD->isExternallyVisible())
         UndefinedButUsed.erase(FD);
       else if (FD->isInlined() &&
-               (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+               !LangOpts.GNUInline &&
                (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
         UndefinedButUsed.erase(FD);
     }
index 659e1b5221187a997a7f6ad52bebe379434ffdc9..8dee0eebc5158ecb1f8743da1c56dfec6ac75638 100644 (file)
@@ -12231,7 +12231,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
     if (mightHaveNonExternalLinkage(Func))
       UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
     else if (Func->getMostRecentDecl()->isInlined() &&
-             (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+             !LangOpts.GNUInline &&
              !Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
       UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
   }
index 612f17c80eb19078cfd5557137be6a526abb3636..a45bccc5132863726f87b676a108894f55cd05d1 100644 (file)
@@ -49,6 +49,7 @@
 // CHECK3-NOT: unreferenced
 // CHECK3-LABEL: define void @_Z10gnu_inlinev()
 // CHECK3-LABEL: define available_externally void @_Z13gnu_ei_inlinev()
+// CHECK3-NOT: @_Z5testCv
 // CHECK3-LABEL: define linkonce_odr i32 @_Z2eiv()
 
 // RUN: echo "MS C Mode tests:"
diff --git a/test/Frontend/gnu-inline.c b/test/Frontend/gnu-inline.c
new file mode 100644 (file)
index 0000000..0272df7
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -std=c89 -fsyntax-only -x c -E -dM %s | FileCheck --check-prefix=GNU-INLINE %s
+// RUN: %clang_cc1 -std=c99 -fsyntax-only -x c -E -dM %s | FileCheck --check-prefix=STDC-INLINE %s
+// RUN: %clang_cc1 -std=c99 -fgnu89-inline -fsyntax-only -x c -E -dM %s | FileCheck --check-prefix=GNU-INLINE %s
+// RUN: %clang_cc1 -fsyntax-only -x c++ -E -dM %s | FileCheck --check-prefix=GNU-INLINE %s
+// RUN: not %clang_cc1 -fgnu89-inline -fsyntax-only -x c++ %s 2>&1 | FileCheck --check-prefix=CXX %s
+
+// CXX: '-fgnu89-inline' not allowed with 'C++/ObjC++'
+
+// STDC-INLINE-NOT: __GNUC_GNU_INLINE__
+// STDC-INLINE: #define __GNUC_STDC_INLINE__ 1
+// STDC-INLINE-NOT: __GNUC_GNU_INLINE__
+
+// GNU-INLINE-NOT: __GNUC_STDC_INLINE__
+// GNU-INLINE: #define __GNUC_GNU_INLINE__ 1
+// GNU-INLINE-NOT: __GNUC_STDC_INLINE__