From: Michael J. Spencer Date: Mon, 18 Jun 2012 07:00:48 +0000 (+0000) Subject: [MSExtensions] Add support for __forceinline. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=adc6cbf5b502f1b58078455ab4fca66c7daac239;p=clang [MSExtensions] Add support for __forceinline. __forceinline is a combination of the inline keyword and __attribute__((always_inline)) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158653 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 2e23c6403b..fd97102341 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -824,6 +824,10 @@ def DLLImport : InheritableAttr { let Spellings = ["dllimport"]; } +def ForceInline : InheritableAttr { + let Spellings = ["__forceinline"]; +} + def Win64 : InheritableAttr { let Spellings = ["__w64"]; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e64a20403c..c72b8665f3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -518,7 +518,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, F->addFnAttr(llvm::Attribute::NoInline); // (noinline wins over always_inline, and we can't specify both in IR) - if (D->hasAttr() && + if ((D->hasAttr() || D->hasAttr()) && !F->hasFnAttr(llvm::Attribute::NoInline)) F->addFnAttr(llvm::Attribute::AlwaysInline); @@ -935,7 +935,7 @@ CodeGenModule::shouldEmitFunction(const FunctionDecl *F) { if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage) return true; if (CodeGenOpts.OptimizationLevel == 0 && - !F->hasAttr()) + !F->hasAttr() && !F->hasAttr()) return false; // PR9614. Avoid cases where the source code is lying to us. An available // externally function should have an equivalent function somewhere else, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f48f9e8c68..ee394f885b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2251,9 +2251,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; // Microsoft single token adornments. - case tok::kw___forceinline: - // FIXME: Add handling here! - break; + case tok::kw___forceinline: { + isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0); + continue; + } case tok::kw___ptr64: case tok::kw___ptr32: diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 516f697652..b8df752b38 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3888,6 +3888,13 @@ static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } +static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.MicrosoftExt) + D->addAttr(::new (S.Context) ForceInlineAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -4082,6 +4089,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ptr64: handlePortabilityAttr(S, D, Attr); break; + case AttributeList::AT_forceinline: + handleForceInlineAttr(S, D, Attr); + break; // Thread safety attributes: case AttributeList::AT_guarded_var: diff --git a/test/CodeGen/forceinline.c b/test/CodeGen/forceinline.c new file mode 100644 index 0000000000..9a21c0dd2c --- /dev/null +++ b/test/CodeGen/forceinline.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple i686-win32 -emit-llvm -fms-extensions < %s | FileCheck %s + +void bar() { +} + +// CHECK-NOT: foo +__forceinline void foo() { + bar(); +} + +void i_want_bar() { +// CHECK: call void @bar + foo(); +}