]> granicus.if.org Git - clang/commitdiff
[MSExtensions] Add support for __forceinline.
authorMichael J. Spencer <bigcheesegs@gmail.com>
Mon, 18 Jun 2012 07:00:48 +0000 (07:00 +0000)
committerMichael J. Spencer <bigcheesegs@gmail.com>
Mon, 18 Jun 2012 07:00:48 +0000 (07:00 +0000)
__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

include/clang/Basic/Attr.td
lib/CodeGen/CodeGenModule.cpp
lib/Parse/ParseDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/forceinline.c [new file with mode: 0644]

index 2e23c6403b44e49e7c9064efa8d2d2a6e5c48b49..fd971023416917b10367fd3644ed11d237d02b90 100644 (file)
@@ -824,6 +824,10 @@ def DLLImport : InheritableAttr {
   let Spellings = ["dllimport"];
 }
 
+def ForceInline : InheritableAttr {
+  let Spellings = ["__forceinline"];
+}
+
 def Win64 : InheritableAttr {
   let Spellings = ["__w64"];
 }
index e64a20403c61d1ce4efc57e36a23949396813806..c72b8665f35a72df6cce86eac95d2024358b3e80 100644 (file)
@@ -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<AlwaysInlineAttr>() &&
+  if ((D->hasAttr<AlwaysInlineAttr>() || D->hasAttr<ForceInlineAttr>()) &&
       !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<AlwaysInlineAttr>())
+      !F->hasAttr<AlwaysInlineAttr>() && !F->hasAttr<ForceInlineAttr>())
     return false;
   // PR9614. Avoid cases where the source code is lying to us. An available
   // externally function should have an equivalent function somewhere else,
index f48f9e8c6877dabca4c26437bf341f21f0253e2f..ee394f885bca6e9581bab856537f732340fbdd60 100644 (file)
@@ -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:
index 516f6976522c9f70008ea4b76064928031843789..b8df752b38d411588845a70bf484337dc8209743 100644 (file)
@@ -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 (file)
index 0000000..9a21c0d
--- /dev/null
@@ -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();
+}