-fms-extensions: Implement half of #pragma init_seg

Summary:
This pragma is very rare.  We could *hypothetically* lower some uses of
it down to @llvm.global_ctors, but given that GlobalOpt isn't able to
optimize prioritized global ctors today, there's really no point.

If we wanted to do this in the future, I would check if the section used
in the pragma started with ".CRT$XC" and had up to two characters after
it.  Those two characters could form the 16-bit initialization priority
that we support in @llvm.global_ctors.  We would have to teach LLVM to
lower prioritized global ctors on COFF as well.

This should let us compile some silly uses of this pragma in WebKit /
Blink.

Reviewers: rsmith, majnemer

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4549

llvm-svn: 213593
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 478c34f..2c65332 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -87,7 +87,7 @@
         LangOpts.getMSPointerToMemberRepresentationMethod()),
     VtorDispModeStack(1, MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
     DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
-    CodeSegStack(nullptr), VisContext(nullptr),
+    CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
     IsBuildingRecoveryCallExpr(false),
     ExprNeedsCleanups(false), LateTemplateParser(nullptr),
     OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 7c182a1..a7d606d 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -431,6 +431,15 @@
   UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
 }
 
+void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+                                StringLiteral *SegmentName) {
+  // There's no stack to maintain, so we just have a current section.  When we
+  // see the default section, reset our current section back to null so we stop
+  // tacking on unnecessary attributes.
+  CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
+  CurInitSegLoc = PragmaLocation;
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
                              SourceLocation PragmaLoc) {
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3e930f4..bbe6930 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9125,6 +9125,13 @@
     if (const SectionAttr *SA = var->getAttr<SectionAttr>())
       if (UnifySection(SA->getName(), SectionFlags, var))
         var->dropAttr<SectionAttr>();
+
+    // Apply the init_seg attribute if this has an initializer.  If the
+    // initializer turns out to not be dynamic, we'll end up ignoring this
+    // attribute.
+    if (CurInitSeg && var->getInit())
+      var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
+                                               CurInitSegLoc));
   }
 
   // All the following checks are C++ only.