[clang] 7f6e331 - Support `#pragma clang section` directives on MachO targets

Jon Roelofs via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 25 09:31:01 PST 2021


Author: Jon Roelofs
Date: 2021-02-25T09:30:10-08:00
New Revision: 7f6e3316456f939a062aad0eeaac983251a1747c

URL: https://github.com/llvm/llvm-project/commit/7f6e3316456f939a062aad0eeaac983251a1747c
DIFF: https://github.com/llvm/llvm-project/commit/7f6e3316456f939a062aad0eeaac983251a1747c.diff

LOG: Support `#pragma clang section` directives on MachO targets

rdar://59560986

Differential Revision: https://reviews.llvm.org/D97233

Added: 
    clang/test/Sema/pragma-clang-section-macho.c
    llvm/test/CodeGen/AArch64/clang-section-macho.ll

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/TargetInfo.h
    clang/lib/Basic/Targets/OSTargets.h
    clang/lib/Sema/SemaAttr.cpp
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/test/CodeGenCXX/clang-sections.cpp
    llvm/include/llvm/MC/MCSectionMachO.h
    llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/lib/MC/MCParser/DarwinAsmParser.cpp
    llvm/lib/MC/MCSectionMachO.cpp
    llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 40de2d8e5977..8f71962502ae 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3091,6 +3091,8 @@ def err_only_annotate_after_access_spec : Error<
 
 def err_attribute_section_invalid_for_target : Error<
   "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">;
+def err_pragma_section_invalid_for_target : Error<
+  "argument to #pragma section is not valid for this target: %0">;
 def warn_attribute_section_drectve : Warning<
   "#pragma %0(\".drectve\") has undefined behavior, "
   "use #pragma comment(linker, ...) instead">, InGroup<MicrosoftDrectveSection>;

diff  --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index aa5a5bb4ac56..9791cb6bbee7 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -32,6 +32,7 @@
 #include "llvm/ADT/Triple.h"
 #include "llvm/Frontend/OpenMP/OMPGridValues.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/VersionTuple.h"
 #include <cassert>
 #include <string>
@@ -1115,15 +1116,15 @@ class TargetInfo : public virtual TransferrableTargetInfo,
   /// checking on attribute((section("foo"))) specifiers.
   ///
   /// In this case, "foo" is passed in to be checked.  If the section
-  /// specifier is invalid, the backend should return a non-empty string
-  /// that indicates the problem.
+  /// specifier is invalid, the backend should return an Error that indicates
+  /// the problem.
   ///
   /// This hook is a simple quality of implementation feature to catch errors
   /// and give good diagnostics in cases when the assembler or code generator
   /// would otherwise reject the section specifier.
   ///
-  virtual std::string isValidSectionSpecifier(StringRef SR) const {
-    return "";
+  virtual llvm::Error isValidSectionSpecifier(StringRef SR) const {
+    return llvm::Error::success();
   }
 
   /// Set forced language options.

diff  --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h
index 2d6303aa55dc..539466c4f678 100644
--- a/clang/lib/Basic/Targets/OSTargets.h
+++ b/clang/lib/Basic/Targets/OSTargets.h
@@ -114,7 +114,7 @@ class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo : public OSTargetInfo<Target> {
     this->MCountName = "\01mcount";
   }
 
-  std::string isValidSectionSpecifier(StringRef SR) const override {
+  llvm::Error isValidSectionSpecifier(StringRef SR) const override {
     // Let MCSectionMachO validate this.
     StringRef Segment, Section;
     unsigned TAA, StubSize;

diff  --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 6e441a0ded0d..9df2b7f84b57 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -301,6 +301,14 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA
     return;
   }
 
+  if (llvm::Error E =
+          Context.getTargetInfo().isValidSectionSpecifier(SecName)) {
+    Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target)
+        << toString(std::move(E));
+    CSec->Valid = false;
+    return;
+  }
+
   if (UnifySection(SecName, SectionFlags, PragmaLoc))
     return;
 

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b343eb9d10de..7ca5c2fb9c1c 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -40,6 +40,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/Assumptions.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -3052,10 +3053,10 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
 }
 
 bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
-  std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
-  if (!Error.empty()) {
-    Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
-         << 1 /*'section'*/;
+  if (llvm::Error E =
+          Context.getTargetInfo().isValidSectionSpecifier(SecName)) {
+    Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
+        << toString(std::move(E)) << 1 /*'section'*/;
     return false;
   }
   return true;
@@ -3073,10 +3074,9 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
 
   // If the target wants to validate the section specifier, make it happen.
-  std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
-  if (!Error.empty()) {
+  if (llvm::Error E = S.Context.getTargetInfo().isValidSectionSpecifier(Str)) {
     S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
-    << Error;
+        << toString(std::move(E));
     return;
   }
 
@@ -3095,11 +3095,10 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
 // `#pragma code_seg("segname")` uses checkSectionName() instead.
 static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
                              StringRef CodeSegName) {
-  std::string Error =
-      S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
-  if (!Error.empty()) {
+  if (llvm::Error E =
+          S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName)) {
     S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
-        << Error << 0 /*'code-seg'*/;
+        << toString(std::move(E)) << 0 /*'code-seg'*/;
     return false;
   }
 

diff  --git a/clang/test/CodeGenCXX/clang-sections.cpp b/clang/test/CodeGenCXX/clang-sections.cpp
index 39df968bf6b1..f252ece30b0c 100644
--- a/clang/test/CodeGenCXX/clang-sections.cpp
+++ b/clang/test/CodeGenCXX/clang-sections.cpp
@@ -1,11 +1,17 @@
-// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s --check-prefixes=CHECK,ELF
+// RUN: %clang_cc1 -emit-llvm -triple arm64-apple-ios -o - %s | FileCheck %s --check-prefixes=CHECK,MACHO
 // Test that global variables, statics and functions are attached section-attributes
 // as per '#pragma clang section' directives.
 
 extern "C" {
 // test with names for each section
+#ifdef __MACH__
+#pragma clang section bss = "__BSS,__mybss1" data = "__DATA,__mydata1" rodata = "__RODATA,__myrodata1"
+#pragma clang section text = "__TEXT,__mytext1"
+#else
 #pragma clang section bss="my_bss.1" data="my_data.1" rodata="my_rodata.1"
 #pragma clang section text="my_text.1"
+#endif
 int a;      // my_bss.1
 int b = 1;  // my_data.1
 int c[4];   // my_bss.1
@@ -19,7 +25,11 @@ int foo(void) {   // my_text.1
 static int g[2]; // my_bss.1
 #pragma clang section bss=""
 int h; // default - .bss
+#ifdef __MACH__
+#pragma clang section data = "" bss = "__BSS,__mybss2" text = "__TEXT,__mytext2"
+#else
 #pragma clang section data=""  bss="my_bss.2" text="my_text.2"
+#endif
 int i = 0; // my_bss.2
 extern const int j;
 const int j = 4; // default - .rodata
@@ -29,7 +39,11 @@ int goo(void) {  // my_text.2
   static int lstat_h;  // my_bss.2
   return zoo(g, &lstat_h);
 }
+#ifdef __MACH__
+#pragma clang section rodata = "__RODATA,__myrodata2" data = "__DATA,__mydata2" relro = "__RELRO,__myrelro2"
+#else
 #pragma clang section rodata="my_rodata.2" data="my_data.2" relro="my_relro.2"
+#endif
 int l = 5; // my_data.2
 extern const int m;
 const int m = 6; // my_rodata.2
@@ -65,19 +79,26 @@ int hoo(void) {
 //CHECK: @n ={{.*}} global i32 0, align 4
 //CHECK: @o ={{.*}} global i32 6, align 4
 //CHECK: @p ={{.*}} constant i32 7, align 4
-//CHECK: @_ZL5fptrs = internal constant [2 x i32 ()*] [i32 ()* @foo, i32 ()* @goo], align 4 #3
+//CHECK: @_ZL5fptrs = internal constant [2 x i32 ()*] [i32 ()* @foo, i32 ()* @goo], align {{4|8}} #3
 
 //CHECK: define{{.*}} i32 @foo() #5 {
 //CHECK: define{{.*}} i32 @goo() #6 {
 //CHECK: declare i32 @zoo(i32*, i32*) #7
 //CHECK: define{{.*}} i32 @hoo() #8 {
 
-//CHECK: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
-//CHECK: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
-//CHECK: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
-//CHECK: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "relro-section"="my_relro.2" "rodata-section"="my_rodata.2" }
-//CHECK: attributes #4 = { "relro-section"="my_relro.2" }
-//CHECK: attributes #5 = { {{.*"implicit-section-name"="my_text.1".*}} }
-//CHECK: attributes #6 = { {{.*"implicit-section-name"="my_text.2".*}} }
+//ELF: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
+//ELF: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
+//ELF: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
+//ELF: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "relro-section"="my_relro.2" "rodata-section"="my_rodata.2" }
+//ELF: attributes #4 = { "relro-section"="my_relro.2" }
+//ELF: attributes #5 = { {{.*"implicit-section-name"="my_text.1".*}} }
+//ELF: attributes #6 = { {{.*"implicit-section-name"="my_text.2".*}} }
+//MACHO: attributes #0 = { "bss-section"="__BSS,__mybss1" "data-section"="__DATA,__mydata1" "rodata-section"="__RODATA,__myrodata1" }
+//MACHO: attributes #1 = { "data-section"="__DATA,__mydata1" "rodata-section"="__RODATA,__myrodata1" }
+//MACHO: attributes #2 = { "bss-section"="__BSS,__mybss2" "rodata-section"="__RODATA,__myrodata1" }
+//MACHO: attributes #3 = { "bss-section"="__BSS,__mybss2" "data-section"="__DATA,__mydata2" "relro-section"="__RELRO,__myrelro2" "rodata-section"="__RODATA,__myrodata2" }
+//MACHO: attributes #4 = { "relro-section"="__RELRO,__myrelro2" }
+//MACHO: attributes #5 = { {{.*"implicit-section-name"="__TEXT,__mytext1".*}} }
+//MACHO: attributes #6 = { {{.*"implicit-section-name"="__TEXT,__mytext2".*}} }
 //CHECK-NOT: attributes #7 = { {{.*"implicit-section-name".*}} }
 //CHECK-NOT: attributes #8 = { {{.*"implicit-section-name".*}} }

diff  --git a/clang/test/Sema/pragma-clang-section-macho.c b/clang/test/Sema/pragma-clang-section-macho.c
new file mode 100644
index 000000000000..9b358a737156
--- /dev/null
+++ b/clang/test/Sema/pragma-clang-section-macho.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm64-apple-ios
+
+#pragma clang section bss = "" data = "" rodata = "" text = ""
+#pragma clang section bss = "" data = "" rodata = "" text = "__TEXT,__text"
+#pragma clang section bss = "" data = "" rodata = "" text = "badname"                       // expected-error {{argument to #pragma section is not valid for this target: mach-o section specifier requires a segment and section separated by a comma}}
+#pragma clang section bss = "" data = "" rodata = "" text = "__TEXT,__namethatiswaytoolong" // expected-error {{argument to #pragma section is not valid for this target: mach-o section specifier requires a section whose length is between 1 and 16 characters}}
+#pragma clang section
+
+int a;

diff  --git a/llvm/include/llvm/MC/MCSectionMachO.h b/llvm/include/llvm/MC/MCSectionMachO.h
index b67558551d97..bf8940524e5a 100644
--- a/llvm/include/llvm/MC/MCSectionMachO.h
+++ b/llvm/include/llvm/MC/MCSectionMachO.h
@@ -59,14 +59,14 @@ class MCSectionMachO final : public MCSection {
   /// appear after a .section directive in a mach-o flavored .s file.  If
   /// successful, this fills in the specified Out parameters and returns an
   /// empty string.  When an invalid section specifier is present, this returns
-  /// a string indicating the problem. If no TAA was parsed, TAA is not altered,
+  /// an Error indicating the problem. If no TAA was parsed, TAA is not altered,
   /// and TAAWasSet becomes false.
-  static std::string ParseSectionSpecifier(StringRef Spec,       // In.
-                                           StringRef &Segment,   // Out.
-                                           StringRef &Section,   // Out.
-                                           unsigned  &TAA,       // Out.
-                                           bool      &TAAParsed, // Out.
-                                           unsigned  &StubSize); // Out.
+  static Error ParseSectionSpecifier(StringRef Spec,      // In.
+                                     StringRef &Segment,  // Out.
+                                     StringRef &Section,  // Out.
+                                     unsigned &TAA,       // Out.
+                                     bool &TAAParsed,     // Out.
+                                     unsigned &StubSize); // Out.
 
   void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
                             raw_ostream &OS,

diff  --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 2530fdc90378..8f74866187c2 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1129,13 +1129,12 @@ void TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
   StringRef Segment, Section;
   unsigned TAA = 0, StubSize = 0;
   bool TAAParsed;
-  std::string ErrorCode =
-    MCSectionMachO::ParseSectionSpecifier(SectionVal, Segment, Section,
-                                          TAA, TAAParsed, StubSize);
-  if (!ErrorCode.empty())
+  if (Error E = MCSectionMachO::ParseSectionSpecifier(
+          SectionVal, Segment, Section, TAA, TAAParsed, StubSize)) {
     // If invalid, report the error with report_fatal_error.
-    report_fatal_error("Invalid section specifier '" + Section + "': " +
-                       ErrorCode + ".");
+    report_fatal_error("Invalid section specifier '" + Section +
+                       "': " + toString(std::move(E)) + ".");
+  }
 
   // Get the section.
   MCSectionMachO *S = getContext().getMachOSection(
@@ -1159,6 +1158,14 @@ static void checkMachOComdat(const GlobalValue *GV) {
 
 MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
+
+  StringRef SectionName = GO->getSection();
+
+  const Function *F = dyn_cast<Function>(GO);
+  if (F && F->hasFnAttribute("implicit-section-name")) {
+    SectionName = F->getFnAttribute("implicit-section-name").getValueAsString();
+  }
+
   // Parse the section specifier and create it if valid.
   StringRef Segment, Section;
   unsigned TAA = 0, StubSize = 0;
@@ -1166,14 +1173,12 @@ MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
 
   checkMachOComdat(GO);
 
-  std::string ErrorCode =
-    MCSectionMachO::ParseSectionSpecifier(GO->getSection(), Segment, Section,
-                                          TAA, TAAParsed, StubSize);
-  if (!ErrorCode.empty()) {
+  if (Error E = MCSectionMachO::ParseSectionSpecifier(
+          SectionName, Segment, Section, TAA, TAAParsed, StubSize)) {
     // If invalid, report the error with report_fatal_error.
     report_fatal_error("Global variable '" + GO->getName() +
                        "' has an invalid section specifier '" +
-                       GO->getSection() + "': " + ErrorCode + ".");
+                       GO->getSection() + "': " + toString(std::move(E)) + ".");
   }
 
   // Get the section.

diff  --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
index 926483451259..f56013869a6d 100644
--- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -23,6 +23,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/SectionKind.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SMLoc.h"
@@ -689,12 +690,9 @@ bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
   unsigned StubSize;
   unsigned TAA;
   bool TAAParsed;
-  std::string ErrorStr =
-    MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
-                                          TAA, TAAParsed, StubSize);
-
-  if (!ErrorStr.empty())
-    return Error(Loc, ErrorStr);
+  if (class Error E = MCSectionMachO::ParseSectionSpecifier(
+          SectionSpec, Segment, Section, TAA, TAAParsed, StubSize))
+    return Error(Loc, toString(std::move(E)));
 
   // Issue a warning if the target is not powerpc and Section is a *coal* section.
   Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple();

diff  --git a/llvm/lib/MC/MCSectionMachO.cpp b/llvm/lib/MC/MCSectionMachO.cpp
index 794d2c52d7b1..d914e64ca23a 100644
--- a/llvm/lib/MC/MCSectionMachO.cpp
+++ b/llvm/lib/MC/MCSectionMachO.cpp
@@ -174,12 +174,12 @@ bool MCSectionMachO::isVirtualSection() const {
 /// flavored .s file.  If successful, this fills in the specified Out
 /// parameters and returns an empty string.  When an invalid section
 /// specifier is present, this returns a string indicating the problem.
-std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
-                                                  StringRef &Segment,    // Out.
-                                                  StringRef &Section,    // Out.
-                                                  unsigned  &TAA,        // Out.
-                                                  bool      &TAAParsed,  // Out.
-                                                  unsigned  &StubSize) { // Out.
+Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec,       // In.
+                                            StringRef &Segment,   // Out.
+                                            StringRef &Section,   // Out.
+                                            unsigned &TAA,        // Out.
+                                            bool &TAAParsed,      // Out.
+                                            unsigned &StubSize) { // Out.
   TAAParsed = false;
 
   SmallVector<StringRef, 5> SplitSpec;
@@ -194,25 +194,23 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
   StringRef Attrs = GetEmptyOrTrim(3);
   StringRef StubSizeStr = GetEmptyOrTrim(4);
 
-  // Verify that the segment is present and not too long.
-  if (Segment.empty() || Segment.size() > 16)
-    return "mach-o section specifier requires a segment whose length is "
-           "between 1 and 16 characters";
-
-  // Verify that the section is present and not too long.
+  // Verify that the section is present.
   if (Section.empty())
-    return "mach-o section specifier requires a segment and section "
-           "separated by a comma";
+    return createStringError(inconvertibleErrorCode(),
+                             "mach-o section specifier requires a segment "
+                             "and section separated by a comma");
 
+  // Verify that the section is not too long.
   if (Section.size() > 16)
-    return "mach-o section specifier requires a section whose length is "
-           "between 1 and 16 characters";
+    return createStringError(inconvertibleErrorCode(),
+                             "mach-o section specifier requires a section "
+                             "whose length is between 1 and 16 characters");
 
   // If there is no comma after the section, we're done.
   TAA = 0;
   StubSize = 0;
   if (SectionType.empty())
-    return "";
+    return Error::success();
 
   // Figure out which section type it is.
   auto TypeDescriptor =
@@ -223,7 +221,9 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
 
   // If we didn't find the section type, reject it.
   if (TypeDescriptor == std::end(SectionTypeDescriptors))
-    return "mach-o section specifier uses an unknown section type";
+    return createStringError(inconvertibleErrorCode(),
+                             "mach-o section specifier uses an unknown "
+                             "section type");
 
   // Remember the TypeID.
   TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
@@ -233,9 +233,10 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
   if (Attrs.empty()) {
     // S_SYMBOL_STUBS always require a symbol stub size specifier.
     if (TAA == MachO::S_SYMBOL_STUBS)
-      return "mach-o section specifier of type 'symbol_stubs' requires a size "
-             "specifier";
-    return "";
+      return createStringError(inconvertibleErrorCode(),
+                               "mach-o section specifier of type "
+                               "'symbol_stubs' requires a size specifier");
+    return Error::success();
   }
 
   // The attribute list is a '+' separated list of attributes.
@@ -249,7 +250,9 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
                         return SectionAttr.trim() == Descriptor.AssemblerName;
                       });
     if (AttrDescriptorI == std::end(SectionAttrDescriptors))
-      return "mach-o section specifier has invalid attribute";
+      return createStringError(inconvertibleErrorCode(),
+                               "mach-o section specifier has invalid "
+                               "attribute");
 
     TAA |= AttrDescriptorI->AttrFlag;
   }
@@ -258,19 +261,24 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
   if (StubSizeStr.empty()) {
     // S_SYMBOL_STUBS always require a symbol stub size specifier.
     if (TAA == MachO::S_SYMBOL_STUBS)
-      return "mach-o section specifier of type 'symbol_stubs' requires a size "
-      "specifier";
-    return "";
+      return createStringError(inconvertibleErrorCode(),
+                               "mach-o section specifier of type "
+                               "'symbol_stubs' requires a size specifier");
+    return Error::success();
   }
 
   // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
   if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
-    return "mach-o section specifier cannot have a stub size specified because "
-           "it does not have type 'symbol_stubs'";
+    return createStringError(inconvertibleErrorCode(),
+                             "mach-o section specifier cannot have a stub "
+                             "size specified because it does not have type "
+                             "'symbol_stubs'");
 
   // Convert the stub size from a string to an integer.
   if (StubSizeStr.getAsInteger(0, StubSize))
-    return "mach-o section specifier has a malformed stub size";
+    return createStringError(inconvertibleErrorCode(),
+                             "mach-o section specifier has a malformed "
+                             "stub size");
 
-  return "";
+  return Error::success();
 }

diff  --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index dcfff19de013..551dd7530d84 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1919,9 +1919,8 @@ bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const {
       StringRef ParsedSegment, ParsedSection;
       unsigned TAA = 0, StubSize = 0;
       bool TAAParsed;
-      std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier(
-          Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize);
-      assert(ErrorCode.empty() && "Invalid section specifier.");
+      cantFail(MCSectionMachO::ParseSectionSpecifier(
+          Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize));
 
       // Ignore the globals from the __OBJC section. The ObjC runtime assumes
       // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to

diff  --git a/llvm/test/CodeGen/AArch64/clang-section-macho.ll b/llvm/test/CodeGen/AArch64/clang-section-macho.ll
new file mode 100644
index 000000000000..1c23f4c0a144
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/clang-section-macho.ll
@@ -0,0 +1,11 @@
+;RUN: llc -mtriple=arm64-apple-ios %s -o - | FileCheck %s
+
+define dso_local void @foo() #0 {
+entry:
+  ret void
+}
+
+attributes #0 = { "implicit-section-name"="__TEXT,__mytext" }
+
+; CHECK:      .section	__TEXT,__mytext
+; CHECK-NEXT: .globl	_foo


        


More information about the cfe-commits mailing list