From 4afd81447ff830f25fbd2b328e1bec69e225fb9f Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 13 May 2015 22:07:22 +0000 Subject: [PATCH] Make GNUInline consistent with whether we use traditional GNU inline semantics. 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 | 11 ++++++++--- lib/Frontend/InitPreprocessor.cpp | 2 +- lib/Sema/SemaDecl.cpp | 4 ++-- lib/Sema/SemaExpr.cpp | 2 +- test/CodeGen/inline.c | 1 + test/Frontend/gnu-inline.c | 15 +++++++++++++++ 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 test/Frontend/gnu-inline.c diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5e59800c5f..d2514acd6d 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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) diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index d9ae3ba81d..0d97709607 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -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__"); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ac8f57698b..8be7286f66 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2710,7 +2710,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // UndefinedButUsed. if (!Old->isInlined() && New->isInlined() && !New->hasAttr() && - (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())) UndefinedButUsed.erase(FD); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 659e1b5221..8dee0eebc5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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()) UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); } diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c index 612f17c80e..a45bccc513 100644 --- a/test/CodeGen/inline.c +++ b/test/CodeGen/inline.c @@ -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 index 0000000000..0272df7e71 --- /dev/null +++ b/test/Frontend/gnu-inline.c @@ -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__ -- 2.40.0