[Clang][Sema] Capturing section type conflicts on #pragma clang section

Summary:
Section names used in clang section pragmas were not validated against
previously defined sections, causing section type conflicts to be
ignored by Sema.

This patch enables Clang to capture these section type conflicts by
using the existing Sema's UnifySection method to validate section names
from clang section pragmas.

Reviewers: hans, rnk, javed.absar

Reviewed By: rnk

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D78572
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index cd7021a..5f8e7fc 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2978,6 +2978,7 @@
     PSF_Write = 0x2,
     PSF_Execute = 0x4,
     PSF_Implicit = 0x8,
+    PSF_ZeroInit = 0x10,
     PSF_Invalid = 0x80000000U,
   };
 
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 828d429..816aaf9f0 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -1873,6 +1873,7 @@
       return;
     }
 
+    SourceLocation PragmaLocation = Tok.getLocation();
     PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
     if (Tok.isNot(tok::equal)) {
       PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
@@ -1883,10 +1884,11 @@
     if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
       return;
 
-    Actions.ActOnPragmaClangSection(Tok.getLocation(),
-      (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
-                       Sema::PragmaClangSectionAction::PCSA_Clear),
-       SecKind, SecName);
+    Actions.ActOnPragmaClangSection(
+        PragmaLocation,
+        (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
+                        : Sema::PragmaClangSectionAction::PCSA_Clear),
+        SecKind, SecName);
   }
 }
 
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 50089de..b5cb96d 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -256,12 +256,15 @@
 void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
                                    PragmaClangSectionKind SecKind, StringRef SecName) {
   PragmaClangSection *CSec;
+  int SectionFlags = ASTContext::PSF_Read;
   switch (SecKind) {
     case PragmaClangSectionKind::PCSK_BSS:
       CSec = &PragmaClangBSSSection;
+      SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit;
       break;
     case PragmaClangSectionKind::PCSK_Data:
       CSec = &PragmaClangDataSection;
+      SectionFlags |= ASTContext::PSF_Write;
       break;
     case PragmaClangSectionKind::PCSK_Rodata:
       CSec = &PragmaClangRodataSection;
@@ -271,6 +274,7 @@
       break;
     case PragmaClangSectionKind::PCSK_Text:
       CSec = &PragmaClangTextSection;
+      SectionFlags |= ASTContext::PSF_Execute;
       break;
     default:
       llvm_unreachable("invalid clang section kind");
@@ -281,6 +285,9 @@
     return;
   }
 
+  if (UnifySection(SecName, SectionFlags, PragmaLoc))
+    return;
+
   CSec->Valid = true;
   CSec->SectionName = std::string(SecName);
   CSec->PragmaLocation = PragmaLoc;
diff --git a/clang/test/Sema/pragma-clang-section.c b/clang/test/Sema/pragma-clang-section.c
index 38a3bc9..97d10f5 100644
--- a/clang/test/Sema/pragma-clang-section.c
+++ b/clang/test/Sema/pragma-clang-section.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi
-#pragma clang section bss="mybss.1" data="mydata.1" rodata="myrodata.1" text="mytext.1"
+#pragma clang section bss = "mybss.1" data = "mydata.1" rodata = "myrodata.1" text = "mytext.1" // expected-note 2 {{#pragma entered here}}
 #pragma clang section bss="" data="" rodata="" text=""
 #pragma clang section
 
@@ -16,4 +16,10 @@
 #pragma clang section text "text.2"   // expected-error {{expected '=' following '#pragma clang section text'}}
 #pragma clang section relro "relro.2"   // expected-error {{expected '=' following '#pragma clang section relro'}}
 #pragma clang section bss="" data="" rodata="" text="" more //expected-error {{expected one of [bss|data|rodata|text|relro] section kind in '#pragma clang section'}}
+
+#pragma clang section bss = "mybss.3" data = "mybss.3" // expected-error {{this causes a section type conflict with a prior #pragma section}} expected-note {{#pragma entered here}} expected-note {{#pragma entered here}}
+#pragma clang section rodata = "mydata.1"              // expected-error {{this causes a section type conflict with a prior #pragma section}}
+#pragma clang section bss = "myrodata.1"               // expected-error {{this causes a section type conflict with a prior #pragma section}}
+#pragma clang section text = "mybss.3"                 // expected-error {{this causes a section type conflict with a prior #pragma section}}
+
 int a;