strimo378 created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
strimo378 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158242

Files:
  clang/include/clang/Basic/Attr.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/attr-linkage.c

Index: clang/test/CodeGen/attr-linkage.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-linkage.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -emit-llvm -Wno-gcc-compat -O1 -disable-llvm-passes -o - %s | FileCheck %s
+
+int v01 __attribute__((linkage("external")));
+int v02 __attribute__((linkage("available_externally")));
+int v03 __attribute__((linkage("linkonce")));
+int v04 __attribute__((linkage("linkonce_odr")));
+int v05 __attribute__((linkage("weak")));
+int v06 __attribute__((linkage("weak_odr")));
+int v07[3] __attribute__((linkage("appending")));
+int v08 __attribute__((linkage("internal")));
+int v09 __attribute__((linkage("private")));
+int v10 __attribute__((linkage("external_weak")));
+int v11 __attribute__((linkage("common")));
+
+// CHECK: @v01 = global i32 0
+// CHECK: @v02 = available_externally global i32 0
+// CHECK: @v03 = linkonce global i32 0
+// CHECK: @v04 = linkonce_odr global i32 0
+// CHECK: @v05 = weak global i32 0
+// CHECK: @v06 = weak_odr global i32 0
+// CHECK: @v07 = appending global [3 x i32] zeroinitializer
+// CHECK: @v08 = internal global i32 0
+// CHECK: @v09 = private global i32 0
+// CHECK: @v10 = extern_weak global i32 0
+// CHECK: @v11 = common global i32 0
+
+void f01(void) __attribute__((linkage("external"))) {};
+void f02(void) __attribute__((linkage("available_externally"))) {};
+void f03(void) __attribute__((linkage("linkonce"))) {};
+void f04(void) __attribute__((linkage("linkonce_odr"))) {};
+void f05(void) __attribute__((linkage("weak"))) {};
+void f06(void) __attribute__((linkage("weak_odr"))) {};
+// appending is only applicable to variables
+void f08(void) __attribute__((linkage("internal"))) {};
+void f09(void) __attribute__((linkage("private"))) {};
+void f10(void) __attribute__((linkage("external_weak"))) {};
+// common is only applicable to variables
+
+// CHECK: define dso_local void @f01()
+// CHECK: define available_externally void @f02()
+// CHECK: define linkonce void @f03()
+// CHECK: define linkonce_odr void @f04()
+// CHECK: define weak void @f05()
+// CHECK: define weak_odr void @f06()
+// CHECK: define internal void @f08()
+// CHECK: define private void @f09()
+// CHECK: define extern_weak void @f10()
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2365,6 +2365,29 @@
   D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority));
 }
 
+static void handleLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // Linkage attributes don't mean anything on a typedef.
+  if (isa<TypedefNameDecl>(D)) {
+    S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
+    return;
+  }
+
+  // Check that the argument is a string literal.
+  StringRef TypeStr;
+  SourceLocation LiteralLoc;
+  if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
+    return;
+
+  LinkageAttr::LinkageType type;
+  if (!LinkageAttr::ConvertStrToLinkageType(TypeStr, type)) {
+    S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
+        << AL << TypeStr;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) LinkageAttr(S.Context, AL, type));
+}
+
 static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   uint32_t priority = DestructorAttr::DefaultPriority;
   if (AL.getNumArgs() &&
@@ -8878,6 +8901,9 @@
     S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)
         << AL << AL.isRegularKeywordAttribute() << D->getLocation();
     break;
+  case ParsedAttr::AT_Linkage:
+    handleLinkageAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_Interrupt:
     handleInterruptAttr(S, D, AL);
     break;
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -5413,6 +5413,36 @@
 llvm::GlobalValue::LinkageTypes
 CodeGenModule::getLLVMLinkageForDeclarator(const DeclaratorDecl *D,
                                            GVALinkage Linkage) {
+
+  if (const auto *A = D->getAttr<LinkageAttr>()) {
+    switch (A->getLinkage()) {
+    case LinkageAttr::Private:
+      return llvm::GlobalValue::PrivateLinkage;
+    case LinkageAttr::Internal:
+      return llvm::GlobalValue::InternalLinkage;
+    case LinkageAttr::WeakAny:
+      return llvm::GlobalValue::WeakAnyLinkage;
+    case LinkageAttr::WeakODR:
+      return llvm::GlobalValue::WeakODRLinkage;
+    case LinkageAttr::LinkOnceAny:
+      return llvm::GlobalValue::LinkOnceAnyLinkage;
+    case LinkageAttr::LinkOnceODR:
+      return llvm::GlobalValue::LinkOnceODRLinkage;
+    case LinkageAttr::AvailableExternally:
+      return llvm::GlobalValue::AvailableExternallyLinkage;
+    case LinkageAttr::Appending:
+      return llvm::GlobalValue::AppendingLinkage;
+    case LinkageAttr::Common:
+      return llvm::GlobalValue::CommonLinkage;
+    case LinkageAttr::ExternalWeak:
+      return llvm::GlobalValue::ExternalWeakLinkage;
+    case LinkageAttr::External:
+      return llvm::GlobalValue::ExternalLinkage;
+    default:
+      llvm_unreachable("unknown linkage");
+    }
+  }
+
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
 
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3036,6 +3036,16 @@
   let Documentation = [Undocumented];
 }
 
+def Linkage : InheritableAttr {
+  let Clone = 0;
+  let Spellings = [GCC<"linkage">];
+  let Args = [EnumArgument<"Linkage", "LinkageType",
+                           ["external", "available_externally", "linkonce", "linkonce_odr", "weak", "weak_odr", "appending", "internal", "private", "external_weak", "common"],
+                           ["External", "AvailableExternally", "LinkOnceAny", "LinkOnceODR", "WeakAny", "WeakODR", "Appending", "Internal", "Private", "ExternalWeak", "Common"]>];
+  let MeaningfulToClassTemplateDefinition = 1;
+  let Documentation = [Undocumented];
+}
+
 def TypeVisibility : InheritableAttr {
   let Clone = 0;
   let Spellings = [Clang<"type_visibility">];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to