[cfe-commits] support for Borland extensions and __pascal

dawn at burble.org dawn at burble.org
Tue Aug 31 15:30:08 PDT 2010


This patch adds support for Borland extensions under the option
-fborland-extensions, as well as semantic support for the "__pascal" calling
convention (not yet added to llvm).

At this time, it's not possible to disctinguish between GNU attributes
and those of and other vendors, so the calling convention is supported
the same as MS calling conventions like "__thiscall".
"__attribute__((pascal))" is also supported with this patch for
consistency - I could remove this support, but since clang seems
to want to print "__attribute__((pascal))" for "__pascal", it made more
sense to just allow it.  

Note from the test case that there's an issue with pointer to member
functions which I have yet to diagnose.

Please review,
-Dawn
-------------- next part --------------
Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h	(revision 112654)
+++ include/clang/Basic/LangOptions.h	(working copy)
@@ -34,6 +34,7 @@
   unsigned HexFloats         : 1;  // C99 Hexadecimal float constants.
   unsigned C99               : 1;  // C99 Support
   unsigned Microsoft         : 1;  // Microsoft extensions.
+  unsigned Borland           : 1;  // Borland extensions.
   unsigned CPlusPlus         : 1;  // C++ Support
   unsigned CPlusPlus0x       : 1;  // C++0x Support
   unsigned CXXOperatorNames  : 1;  // Treat C++ operator names as keywords.
@@ -140,7 +141,7 @@
     HexFloats = 0;
     GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
     NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
-    C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
+    C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
     CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
     Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
     NeXTRuntime = 1;
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def	(revision 112654)
+++ include/clang/Basic/TokenKinds.def	(working copy)
@@ -335,6 +335,9 @@
 KEYWORD(__thiscall                  , KEYALL)
 KEYWORD(__forceinline               , KEYALL)
 
+// Borland Extension.
+KEYWORD(__pascal                    , KEYALL)
+
 // Altivec Extension.
 KEYWORD(__vector                    , KEYALTIVEC)
 KEYWORD(__pixel                     , KEYALTIVEC)
@@ -371,6 +374,9 @@
 ALIAS("_stdcall"     , __stdcall  , KEYMS)
 ALIAS("_thiscall"    , __thiscall , KEYMS)
 
+// Borland Extensions.
+ALIAS("_pascal"      , __pascal   , KEYMS)
+
 //===----------------------------------------------------------------------===//
 // Objective-C @-preceeded keywords.
 //===----------------------------------------------------------------------===//
Index: include/clang/Sema/AttributeList.h
===================================================================
--- include/clang/Sema/AttributeList.h	(revision 112654)
+++ include/clang/Sema/AttributeList.h	(working copy)
@@ -102,6 +102,7 @@
     AT_ownership_returns,  // Clang-specific.
     AT_ownership_takes,    // Clang-specific.
     AT_packed,
+    AT_pascal,
     AT_pure,
     AT_regparm,
     AT_section,
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 112654)
+++ include/clang/AST/Type.h	(working copy)
@@ -410,7 +410,8 @@
   CC_C,           // __attribute__((cdecl))
   CC_X86StdCall,  // __attribute__((stdcall))
   CC_X86FastCall, // __attribute__((fastcall))
-  CC_X86ThisCall  // __attribute__((thiscall))
+  CC_X86ThisCall, // __attribute__((thiscall))
+  CC_X86Pascal    // __attribute__((pascal))
 };
 
 
@@ -1928,7 +1929,7 @@
     // The value passed to __attribute__((regparm(x)))
     unsigned RegParm;
     // The calling convention as specified via
-    // __attribute__((cdecl|stdcall|fastcall|thiscall))
+    // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
     CallingConv CC;
   };
 
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 112654)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1365,6 +1365,7 @@
   AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
   AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
   AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
+  AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0);
   void ParseTypeofSpecifier(DeclSpec &DS);
   void ParseDecltypeSpecifier(DeclSpec &DS);
   
Index: docs/tools/clang.pod
===================================================================
--- docs/tools/clang.pod	(revision 112654)
+++ docs/tools/clang.pod	(working copy)
@@ -168,6 +168,10 @@
 
 Enable support for Microsoft extensions.
 
+=item B<-fborland-extensions>
+
+Enable support for Borland extensions.
+
 =item B<-fwritable-strings>
 
 Make all string literals default to writable.  This disables uniquing of
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp	(revision 112654)
+++ lib/Frontend/CompilerInvocation.cpp	(working copy)
@@ -526,6 +526,8 @@
     Res.push_back("-fgnu-keywords");
   if (Opts.Microsoft)
     Res.push_back("-fms-extensions");
+  if (Opts.Borland)
+    Res.push_back("-fborland-extensions");
   if (Opts.ObjCNonFragileABI)
     Res.push_back("-fobjc-nonfragile-abi");
   if (Opts.ObjCNonFragileABI2)
@@ -1317,6 +1319,7 @@
                                    !Opts.AsmPreprocessor);
   Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
   Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+  Opts.Borland = Args.hasArg(OPT_fborland_extensions);
   Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
   Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
   if (Args.hasArg(OPT_fno_lax_vector_conversions))
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 112654)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -1986,6 +1986,9 @@
   case AttributeList::AT_cdecl:
     d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
     return;
+  case AttributeList::AT_pascal:
+    d->addAttr(::new (S.Context) PascalAttr(Attr.getLoc(), S.Context));
+    return;
   default:
     llvm_unreachable("unexpected attribute kind");
     return;
@@ -2294,6 +2297,7 @@
   case AttributeList::AT_cdecl:
   case AttributeList::AT_fastcall:
   case AttributeList::AT_thiscall:
+  case AttributeList::AT_pascal:
     HandleCallConvAttr(D, Attr, S);
     break;
   default:
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 112654)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -1906,6 +1906,7 @@
   case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
   case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
   case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+  case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
   default: llvm_unreachable("unexpected attribute kind"); return false;
   }
 
@@ -2033,6 +2034,7 @@
     case AttributeList::AT_fastcall:
     case AttributeList::AT_stdcall:
     case AttributeList::AT_thiscall:
+    case AttributeList::AT_pascal:
     case AttributeList::AT_regparm:
       // Don't process these on the DeclSpec.
       if (IsDeclSpec ||
Index: lib/Sema/AttributeList.cpp
===================================================================
--- lib/Sema/AttributeList.cpp	(revision 112654)
+++ lib/Sema/AttributeList.cpp	(working copy)
@@ -126,9 +126,11 @@
     .Case("init_priority", AT_init_priority)
     .Case("no_instrument_function", AT_no_instrument_function)
     .Case("thiscall", AT_thiscall)
+    .Case("pascal", AT_pascal)
     .Case("__cdecl", AT_cdecl)
     .Case("__stdcall", AT_stdcall)
     .Case("__fastcall", AT_fastcall)
     .Case("__thiscall", AT_thiscall)
+    .Case("__pascal", AT_pascal)
     .Default(UnknownAttribute);
 }
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp	(revision 112654)
+++ lib/AST/Type.cpp	(working copy)
@@ -1005,6 +1005,7 @@
   case CC_X86StdCall: return "stdcall";
   case CC_X86FastCall: return "fastcall";
   case CC_X86ThisCall: return "thiscall";
+  case CC_X86Pascal: return "pascal";
   }
 }
 
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp	(revision 112654)
+++ lib/AST/TypePrinter.cpp	(working copy)
@@ -299,6 +299,9 @@
   case CC_X86ThisCall:
     S += " __attribute__((thiscall))";
     break;
+  case CC_X86Pascal:
+    S += " __attribute__((pascal))";
+    break;
   }
   if (Info.getNoReturn())
     S += " __attribute__((noreturn))";
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 112654)
+++ lib/Driver/Tools.cpp	(working copy)
@@ -1215,6 +1215,11 @@
                    getToolChain().getTriple().getOS() == llvm::Triple::Win32))
     CmdArgs.push_back("-fms-extensions");
 
+  // -fborland-extensions=0 is default.
+  if (Args.hasFlag(options::OPT_fborland_extensions,
+		   options::OPT_fno_borland_extensions))
+    CmdArgs.push_back("-fborland-extensions");
+
   // -fgnu-keywords default varies depending on language; only pass if
   // specified.
   if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp	(revision 112654)
+++ lib/CodeGen/MicrosoftCXXABI.cpp	(working copy)
@@ -919,6 +919,7 @@
   switch (T->getCallConv()) {
     case CC_Default:
     case CC_C: Out << 'A'; break;
+    case CC_X86Pascal: Out << 'C'; break;
     case CC_X86ThisCall: Out << 'E'; break;
     case CC_X86StdCall: Out << 'G'; break;
     case CC_X86FastCall: Out << 'I'; break;
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp	(revision 112654)
+++ lib/CodeGen/CGCall.cpp	(working copy)
@@ -36,6 +36,7 @@
   case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
   case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
   case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
+  // TODO: add support for CC_X86Pascal to llvm
   }
 }
 
@@ -100,6 +101,9 @@
   if (D->hasAttr<ThisCallAttr>())
     return CC_X86ThisCall;
 
+  if (D->hasAttr<PascalAttr>())
+    return CC_X86Pascal;
+
   return CC_C;
 }
 
Index: lib/Parse/ParseTentative.cpp
===================================================================
--- lib/Parse/ParseTentative.cpp	(revision 112654)
+++ lib/Parse/ParseTentative.cpp	(working copy)
@@ -757,6 +757,10 @@
   case tok::kw___ptr64:
   case tok::kw___forceinline:
     return TPResult::True();
+
+    // Borland
+  case tok::kw___pascal:
+    return TPResult::True();
   
     // AltiVec
   case tok::kw___vector:
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 112654)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -293,6 +293,17 @@
   return CurrAttr;
 }
 
+AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
+  // Treat these like attributes
+  while (Tok.is(tok::kw___pascal)) {
+    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+    SourceLocation AttrNameLoc = ConsumeToken();
+    CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+                                 SourceLocation(), 0, 0, CurrAttr, true);
+  }
+  return CurrAttr;
+}
+
 /// ParseDeclaration - Parse a full 'declaration', which consists of
 /// declaration-specifiers, some number of declarators, and a semicolon.
 /// 'Context' should be a Declarator::TheContext value.  This returns the
@@ -1207,6 +1218,11 @@
       DS.AddAttributes(ParseMicrosoftTypeAttributes());
       continue;
 
+    // Borland single token adornments.
+    case tok::kw___pascal:
+      DS.AddAttributes(ParseBorlandTypeAttributes());
+      continue;
+
     // storage-class-specifier
     case tok::kw_typedef:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
@@ -1683,6 +1699,7 @@
 
     isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
     break;
+
   case tok::kw___ptr64:
   case tok::kw___w64:
   case tok::kw___cdecl:
@@ -1692,6 +1709,10 @@
     DS.AddAttributes(ParseMicrosoftTypeAttributes());
     return true;
 
+  case tok::kw___pascal:
+    DS.AddAttributes(ParseBorlandTypeAttributes());
+    return true;
+
   default:
     // Not a type-specifier; do nothing.
     return false;
@@ -2268,6 +2289,7 @@
   case tok::kw___thiscall:
   case tok::kw___w64:
   case tok::kw___ptr64:
+  case tok::kw___pascal:
     return true;
   }
 }
@@ -2376,6 +2398,7 @@
   case tok::kw___w64:
   case tok::kw___ptr64:
   case tok::kw___forceinline:
+  case tok::kw___pascal:
     return true;
   }
 }
@@ -2427,15 +2450,20 @@
 }
 
 /// ParseTypeQualifierListOpt
-///       type-qualifier-list: [C99 6.7.5]
-///         type-qualifier
-/// [GNU]   attributes                        [ only if AttributesAllowed=true ]
-///         type-qualifier-list type-qualifier
-/// [GNU]   type-qualifier-list attributes    [ only if AttributesAllowed=true ]
-/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
-///           if CXX0XAttributesAllowed = true
+///          type-qualifier-list: [C99 6.7.5]
+///            type-qualifier
+/// [vendor]   attributes                        
+///              [ only if VendorAttributesAllowed=true ]
+///            type-qualifier-list type-qualifier
+/// [vendor]   type-qualifier-list attributes    
+///              [ only if VendorAttributesAllowed=true ]
+/// [C++0x]    attribute-specifier[opt] is allowed before cv-qualifier-seq
+///              [ only if CXX0XAttributesAllowed=true ]
+/// Note: vendor can be GNU, MS, etc.
+/// FIXME: would be nice to have bitfields for each vendor.
 ///
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
+                                       bool VendorAttributesAllowed,
                                        bool CXX0XAttributesAllowed) {
   if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
     SourceLocation Loc = Tok.getLocation();
@@ -2476,13 +2504,19 @@
     case tok::kw___stdcall:
     case tok::kw___fastcall:
     case tok::kw___thiscall:
-      if (GNUAttributesAllowed) {
+      if (VendorAttributesAllowed) {
         DS.AddAttributes(ParseMicrosoftTypeAttributes());
         continue;
       }
       goto DoneWithTypeQuals;
+    case tok::kw___pascal:
+      if (VendorAttributesAllowed) {
+        DS.AddAttributes(ParseBorlandTypeAttributes());
+        continue;
+      }
+      goto DoneWithTypeQuals;
     case tok::kw___attribute:
-      if (GNUAttributesAllowed) {
+      if (VendorAttributesAllowed) {
         DS.AddAttributes(ParseGNUAttributes());
         continue; // do *not* consume the next token!
       }
@@ -2867,6 +2901,10 @@
        Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) {
     AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take()));
   }
+  // Eat any Borland extensions.
+  if  (Tok.is(tok::kw___pascal)) {
+    AttrList.reset(ParseBorlandTypeAttributes(AttrList.take()));
+  }
 
   // If we haven't past the identifier yet (or where the identifier would be
   // stored, if this is an abstract declarator), then this is probably just


More information about the cfe-commits mailing list