Add support for Pascal strings.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42974 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index 1558254..ff4b54b 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -419,7 +419,7 @@
 void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
   if (Str->isWide()) OS << 'L';
   OS << '"';
-  
+
   // FIXME: this doesn't print wstrings right.
   for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
     switch (Str->getStrData()[i]) {
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 6d9b6b0..6e8dd9e 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -271,10 +271,15 @@
                 llvm::cl::desc("Do not treat C++ operator name keywords as "
                                "synonyms for operators"));
 
+static llvm::cl::opt<bool>
+PascalStrings("fpascal-strings",
+              llvm::cl::desc("Recognize and construct Pascal-style "
+                             "string literals"));
 // FIXME: add:
 //   -ansi
 //   -trigraphs
 //   -fdollars-in-identifiers
+//   -fpascal-strings
 static void InitializeLanguageStandard(LangOptions &Options) {
   if (LangStd == lang_unspecified) {
     // Based on the base language, pick one.
@@ -325,6 +330,7 @@
   
   Options.Trigraphs = 1; // -trigraphs or -ansi
   Options.DollarIdents = 1;  // FIXME: Really a target property.
+  Options.PascalStrings = PascalStrings;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/Lex/LiteralSupport.cpp b/Lex/LiteralSupport.cpp
index 90a05f6..c0027f2 100644
--- a/Lex/LiteralSupport.cpp
+++ b/Lex/LiteralSupport.cpp
@@ -599,6 +599,8 @@
   // wide strings as appropriate.
   ResultPtr = &ResultBuf[0];   // Next byte to fill in.
   
+  Pascal = false;
+  
   for (unsigned i = 0, e = NumStringToks; i != e; ++i) {
     const char *ThisTokBuf = &TokenBuf[0];
     // Get the spelling of the token, which eliminates trigraphs, etc.  We know
@@ -619,6 +621,19 @@
     assert(ThisTokBuf[0] == '"' && "Expected quote, lexer broken?");
     ++ThisTokBuf;
     
+    // Check if this is a pascal string
+    if (pp.getLangOptions().PascalStrings && ThisTokBuf + 1 != ThisTokEnd &&
+        ThisTokBuf[0] == '\\' && ThisTokBuf[1] == 'p') {
+      
+      // If the \p sequence is found in the first token, we have a pascal string
+      // Otherwise, if we already have a pascal string, ignore the first \p
+      if (i == 0) {
+        ++ThisTokBuf;
+        Pascal = true;
+      } else if (Pascal)
+        ThisTokBuf += 2;
+    }
+      
     while (ThisTokBuf != ThisTokEnd) {
       // Is this a span of non-escape characters?
       if (ThisTokBuf[0] != '\\') {
@@ -665,4 +680,7 @@
     for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
     *ResultPtr++ = 0;
   }
+    
+  if (Pascal) 
+    ResultBuf[0] = ResultPtr-&ResultBuf[0]-1;
 }
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 904230f..471312b 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -46,11 +46,22 @@
     StringTokLocs.push_back(StringToks[i].getLocation());
   
   // FIXME: handle wchar_t
-  QualType t = Context.getPointerType(Context.CharTy);
+  QualType t;
+  
+  if (Literal.Pascal) 
+    t = Context.getPointerType(Context.UnsignedCharTy);
+  else
+    t = Context.getPointerType(Context.CharTy);
+  
+  if (Literal.Pascal && Literal.GetStringLength() > 256)
+    return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
+                SourceRange(StringToks[0].getLocation(),
+                            StringToks[NumStringToks-1].getLocation()));
   
   // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
   return new StringLiteral(Literal.GetString(), Literal.GetStringLength(), 
-                           Literal.AnyWide, t, StringToks[0].getLocation(),
+                           Literal.AnyWide, t, 
+                           StringToks[0].getLocation(),
                            StringToks[NumStringToks-1].getLocation());
 }
 
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index b88c381..75d9388 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -742,6 +742,7 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+			compatibilityVersion = "Xcode 2.4";
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 2a8900c..e2b055b 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -771,6 +771,8 @@
      "'__builtin_choose_expr' requires a constant expression")
 DIAG(warn_unused_expr, WARNING,
      "expression result unused")
+DIAG(err_pascal_string_too_long, ERROR,
+    "Pascal string is too long")
 
 // CHECK: printf format string errors
 DIAG(warn_printf_not_string_constant, WARNING,
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index a2d07f0..afd91e2 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -34,10 +34,12 @@
   unsigned ObjC1             : 1;  // Objective C 1 support enabled.
   unsigned ObjC2             : 1;  // Objective C 2 support enabled.
   
+  unsigned PascalStrings     : 1;  // Allow Pascal strings
+  
   LangOptions() {
     Trigraphs = BCPLComment = DollarIdents = Digraphs = ObjC1 = ObjC2 = 0;
     C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
-    CXXOperatorNames = 0;
+    CXXOperatorNames = PascalStrings = 0;
   }
 };
 
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index dde2d91..e8650fc 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -150,6 +150,7 @@
                       Preprocessor &PP, TargetInfo &T);
   bool hadError;
   bool AnyWide;
+  bool Pascal;
   
   const char *GetString() { return &ResultBuf[0]; }
   unsigned GetStringLength() { return ResultPtr-&ResultBuf[0]; }