r182535 - Adding in parsing and the start of semantic support for __sptr and __uptr pointer type qualifiers. This patch also fixes the correlated __ptr32 and __ptr64 pointer qualifiers so that they are truly type attributes instead of declaration attributes.

Aaron Ballman aaron at aaronballman.com
Wed May 22 16:25:32 PDT 2013


Author: aaronballman
Date: Wed May 22 18:25:32 2013
New Revision: 182535

URL: http://llvm.org/viewvc/llvm-project?rev=182535&view=rev
Log:
Adding in parsing and the start of semantic support for __sptr and __uptr pointer type qualifiers.  This patch also fixes the correlated __ptr32 and __ptr64 pointer qualifiers so that they are truly type attributes instead of declaration attributes.

For more information about __sptr and __uptr, see MSDN: http://msdn.microsoft.com/en-us/library/aa983399.aspx

Patch reviewed by Richard Smith.

Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/Parser/MicrosoftExtensions.c
    cfe/trunk/test/Sema/MicrosoftCompatibility.cpp
    cfe/trunk/test/Sema/MicrosoftExtensions.c
    cfe/trunk/test/Sema/attr-print.c

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed May 22 18:25:32 2013
@@ -3335,7 +3335,11 @@ public:
     attr_thiscall,
     attr_pascal,
     attr_pnaclcall,
-    attr_inteloclbicc
+    attr_inteloclbicc,
+    attr_ptr32,
+    attr_ptr64,
+    attr_sptr,
+    attr_uptr
   };
 
 private:
@@ -3365,6 +3369,17 @@ public:
   bool isSugared() const { return true; }
   QualType desugar() const { return getEquivalentType(); }
 
+  bool isMSTypeSpec() const {
+    switch (getAttrKind()) {
+    default:  return false;
+    case attr_ptr32:
+    case attr_ptr64:
+    case attr_sptr:
+    case attr_uptr:
+      return true;
+    }
+  }
+
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
   }

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed May 22 18:25:32 2013
@@ -978,6 +978,14 @@ def Ptr64 : InheritableAttr {
   let Spellings = [Keyword<"__ptr64">];
 }
 
+def SPtr : InheritableAttr {
+  let Spellings = [Keyword<"__sptr">];
+}
+
+def UPtr : InheritableAttr {
+  let Spellings = [Keyword<"__uptr">];
+}
+
 class MSInheritanceAttr : InheritableAttr;
 
 def SingleInheritance : MSInheritanceAttr {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 22 18:25:32 2013
@@ -1788,7 +1788,9 @@ def err_attribute_uuid_malformed_guid :
 def warn_nonnull_pointers_only : Warning<
   "nonnull attribute only applies to pointer arguments">;
 def err_attribute_pointers_only : Error<
-  "'%0' attribute only applies to pointer arguments">;
+  "%0 attribute only applies to pointer arguments">;
+def err_attribute_no_member_pointers : Error<
+  "%0 attribute cannot be used with pointers to members">;
 def err_attribute_invalid_implicit_this_argument : Error<
   "'%0' attribute is invalid for the implicit this argument">;
 def err_ownership_type : Error<
@@ -6192,6 +6194,9 @@ def warn_collection_expr_type : Warning<
 def err_invalid_conversion_between_ext_vectors : Error<
   "invalid conversion between ext-vector type %0 and %1">;
 
+def warn_duplicate_attribute_exact : Warning<
+  "attribute %0 is already applied">, InGroup<IgnoredAttributes>;
+
 def warn_duplicate_attribute : Warning<
   "attribute %0 is already applied with different parameters">,
   InGroup<IgnoredAttributes>;

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed May 22 18:25:32 2013
@@ -509,6 +509,8 @@ ALIAS("__volatile__" , volatile   , KEYA
 // Microsoft extensions which should be disabled in strict conformance mode
 KEYWORD(__ptr64                       , KEYMS)
 KEYWORD(__ptr32                       , KEYMS)
+KEYWORD(__sptr                        , KEYMS)
+KEYWORD(__uptr                        , KEYMS)
 KEYWORD(__w64                         , KEYMS)
 KEYWORD(__uuidof                      , KEYMS | KEYBORLAND)
 KEYWORD(__try                         , KEYMS | KEYBORLAND)

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Wed May 22 18:25:32 2013
@@ -1072,6 +1072,17 @@ void TypePrinter::printAttributedBefore(
     return printBefore(T->getEquivalentType(), OS);
 
   printBefore(T->getModifiedType(), OS);
+
+  if (T->isMSTypeSpec()) {
+    switch (T->getAttrKind()) {
+    default: return;
+    case AttributedType::attr_ptr32: OS << " __ptr32"; break;
+    case AttributedType::attr_ptr64: OS << " __ptr64"; break;
+    case AttributedType::attr_sptr: OS << " __sptr"; break;
+    case AttributedType::attr_uptr: OS << " __uptr"; break;
+}
+    spaceBeforePlaceHolder(OS);
+  }
 }
 
 void TypePrinter::printAttributedAfter(const AttributedType *T,
@@ -1082,8 +1093,12 @@ void TypePrinter::printAttributedAfter(c
     return printAfter(T->getEquivalentType(), OS);
 
   // TODO: not all attributes are GCC-style attributes.
+  if (T->isMSTypeSpec())
+    return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
+  default: llvm_unreachable("This attribute should have been handled already");
   case AttributedType::attr_address_space:
     OS << "address_space(";
     OS << T->getEquivalentType().getAddressSpace();

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed May 22 18:25:32 2013
@@ -601,7 +601,8 @@ void Parser::ParseMicrosoftTypeAttribute
   while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
          Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl)   ||
          Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) ||
-         Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned)) {
+         Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned) ||
+         Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) {
     IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
     attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
@@ -2711,6 +2712,8 @@ void Parser::ParseDeclarationSpecifiers(
       break;
     }
 
+    case tok::kw___sptr:
+    case tok::kw___uptr:
     case tok::kw___ptr64:
     case tok::kw___ptr32:
     case tok::kw___w64:
@@ -4145,6 +4148,8 @@ bool Parser::isDeclarationSpecifier(bool
   case tok::kw___fastcall:
   case tok::kw___thiscall:
   case tok::kw___w64:
+  case tok::kw___sptr:
+  case tok::kw___uptr:
   case tok::kw___ptr64:
   case tok::kw___ptr32:
   case tok::kw___forceinline:
@@ -4321,6 +4326,8 @@ void Parser::ParseTypeQualifierListOpt(D
       ParseOpenCLQualifiers(DS);
       break;
 
+    case tok::kw___sptr:
+    case tok::kw___uptr:
     case tok::kw___w64:
     case tok::kw___ptr64:
     case tok::kw___ptr32:

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Wed May 22 18:25:32 2013
@@ -1122,6 +1122,8 @@ Parser::isCXXDeclarationSpecifier(Parser
   case tok::kw___fastcall:
   case tok::kw___thiscall:
   case tok::kw___w64:
+  case tok::kw___sptr:
+  case tok::kw___uptr:
   case tok::kw___ptr64:
   case tok::kw___ptr32:
   case tok::kw___forceinline:

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed May 22 18:25:32 2013
@@ -4252,7 +4252,7 @@ static void handleArgumentWithTypeTagAtt
     QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);
     if (!BufferTy->isPointerType()) {
       S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
-        << AttrName;
+        << Attr.getName();
     }
   }
 
@@ -4695,15 +4695,7 @@ static void handlePortabilityAttr(Sema &
     return;
 
   AttributeList::Kind Kind = Attr.getKind();
-  if (Kind == AttributeList::AT_Ptr32)
-    D->addAttr(
-        ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context,
-                                    Attr.getAttributeSpellingListIndex()));
-  else if (Kind == AttributeList::AT_Ptr64)
-    D->addAttr(
-        ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context,
-                                    Attr.getAttributeSpellingListIndex()));
-  else if (Kind == AttributeList::AT_Win64)
+    if (Kind == AttributeList::AT_Win64)
     D->addAttr(
         ::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
                                     Attr.getAttributeSpellingListIndex()));
@@ -4754,6 +4746,10 @@ static void ProcessInheritableDeclAttr(S
   case AttributeList::AT_VectorSize:
   case AttributeList::AT_NeonVectorType:
   case AttributeList::AT_NeonPolyVectorType:
+  case AttributeList::AT_Ptr32:
+  case AttributeList::AT_Ptr64:
+  case AttributeList::AT_SPtr:
+  case AttributeList::AT_UPtr:
     // Ignore these, these are type attributes, handled by
     // ProcessTypeAttributes.
     break;
@@ -4946,8 +4942,6 @@ static void ProcessInheritableDeclAttr(S
     handleInheritanceAttr(S, D, Attr);
     break;
   case AttributeList::AT_Win64:
-  case AttributeList::AT_Ptr32:
-  case AttributeList::AT_Ptr64:
     handlePortabilityAttr(S, D, Attr);
     break;
   case AttributeList::AT_ForceInline:

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed May 22 18:25:32 2013
@@ -108,7 +108,14 @@ static void diagnoseBadTypeAttribute(Sem
     case AttributeList::AT_Regparm: \
     case AttributeList::AT_Pcs: \
     case AttributeList::AT_PnaclCall: \
-    case AttributeList::AT_IntelOclBicc \
+    case AttributeList::AT_IntelOclBicc
+
+// Microsoft-specific type qualifiers.
+#define MS_TYPE_ATTRS_CASELIST  \
+    case AttributeList::AT_Ptr32: \
+    case AttributeList::AT_Ptr64: \
+    case AttributeList::AT_SPtr: \
+    case AttributeList::AT_UPtr
 
 namespace {
   /// An object which stores processing state for the entire
@@ -292,6 +299,10 @@ static bool handleFunctionTypeAttr(TypeP
                                    AttributeList &attr,
                                    QualType &type);
 
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
+                                             AttributeList &attr,
+                                             QualType &type);
+
 static bool handleObjCGCTypeAttr(TypeProcessingState &state,
                                  AttributeList &attr, QualType &type);
 
@@ -626,6 +637,10 @@ static void distributeTypeAttrsFromDecla
       distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
       break;
 
+    MS_TYPE_ATTRS_CASELIST:
+      // Microsoft type attributes cannot go after the declarator-id.
+      continue;
+
     default:
       break;
     }
@@ -3298,6 +3313,14 @@ static AttributeList::Kind getAttrListKi
     return AttributeList::AT_PnaclCall;
   case AttributedType::attr_inteloclbicc:
     return AttributeList::AT_IntelOclBicc;
+  case AttributedType::attr_ptr32:
+    return AttributeList::AT_Ptr32;
+  case AttributedType::attr_ptr64:
+    return AttributeList::AT_Ptr64;
+  case AttributedType::attr_sptr:
+    return AttributeList::AT_SPtr;
+  case AttributedType::attr_uptr:
+    return AttributeList::AT_UPtr;
   }
   llvm_unreachable("unexpected attribute kind!");
 }
@@ -4174,6 +4197,69 @@ namespace {
   };
 }
 
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
+                                             AttributeList &Attr,
+                                             QualType &Type) {
+  Sema &S = State.getSema();
+
+  AttributeList::Kind Kind = Attr.getKind();
+  QualType Desugared = Type;
+  const AttributedType *AT = dyn_cast<AttributedType>(Type);
+  while (AT) {
+    AttributedType::Kind CurAttrKind = AT->getAttrKind();
+
+    // You cannot specify duplicate type attributes, so if the attribute has
+    // already been applied, flag it.
+    if (getAttrListKind(CurAttrKind) == Kind) {
+      S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
+        << Attr.getName();
+      return true;
+    }
+
+    // You cannot have both __sptr and __uptr on the same type, nor can you
+    // have __ptr32 and __ptr64.
+    if ((CurAttrKind == AttributedType::attr_ptr32 &&
+         Kind == AttributeList::AT_Ptr64) ||
+        (CurAttrKind == AttributedType::attr_ptr64 &&
+         Kind == AttributeList::AT_Ptr32)) {
+      S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+        << "'__ptr32'" << "'__ptr64'";
+      return true;
+    } else if ((CurAttrKind == AttributedType::attr_sptr &&
+                Kind == AttributeList::AT_UPtr) ||
+               (CurAttrKind == AttributedType::attr_uptr &&
+                Kind == AttributeList::AT_SPtr)) {
+      S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+        << "'__sptr'" << "'__uptr'";
+      return true;
+    }
+    
+    Desugared = AT->getEquivalentType();
+    AT = dyn_cast<AttributedType>(Desugared);
+  }
+
+  // Pointer type qualifiers can only operate on pointer types, but not
+  // pointer-to-member types.
+  if (!isa<PointerType>(Desugared)) {
+    S.Diag(Attr.getLoc(), Type->isMemberPointerType() ?
+                          diag::err_attribute_no_member_pointers :
+                          diag::err_attribute_pointers_only) << Attr.getName();
+    return true;
+  }
+
+  AttributedType::Kind TAK;
+  switch (Kind) {
+  default: llvm_unreachable("Unknown attribute kind");
+  case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
+  case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
+  case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
+  case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
+  }
+
+  Type = S.Context.getAttributedType(TAK, Type, Type);
+  return false;
+}
+
 /// Process an individual function attribute.  Returns true to
 /// indicate that the attribute was handled, false if it wasn't.
 static bool handleFunctionTypeAttr(TypeProcessingState &state,
@@ -4576,12 +4662,12 @@ static void processTypeAttrs(TypeProcess
       break;
 
     case AttributeList::AT_Win64:
-    case AttributeList::AT_Ptr32:
-    case AttributeList::AT_Ptr64:
-      // FIXME: Don't ignore these. We have partial handling for them as
-      // declaration attributes in SemaDeclAttr.cpp; that should be moved here.
       attr.setUsedAsTypeAttr();
       break;
+    MS_TYPE_ATTRS_CASELIST:
+      if (!handleMSPointerTypeQualifierAttr(state, attr, type))
+        attr.setUsedAsTypeAttr();
+      break;
 
     case AttributeList::AT_NSReturnsRetained:
       if (!state.getSema().getLangOpts().ObjCAutoRefCount)

Modified: cfe/trunk/test/Parser/MicrosoftExtensions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.c?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.c (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.c Wed May 22 18:25:32 2013
@@ -105,3 +105,14 @@ __declspec() void quux( void ) {
   struct S7 s;
   int i = s.t;	/* expected-warning {{'t' is deprecated}} */
 }
+
+int * __sptr psp;
+int * __uptr pup;
+/* Either ordering is acceptable */
+int * __ptr32 __sptr psp32;
+int * __ptr32 __uptr pup32;
+int * __sptr __ptr64 psp64;
+int * __uptr __ptr64 pup64;
+
+/* Legal to have nested pointer attributes */
+int * __sptr * __ptr32 ppsp32;

Modified: cfe/trunk/test/Sema/MicrosoftCompatibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftCompatibility.cpp?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/test/Sema/MicrosoftCompatibility.cpp (original)
+++ cfe/trunk/test/Sema/MicrosoftCompatibility.cpp Wed May 22 18:25:32 2013
@@ -2,3 +2,9 @@
 
 // PR15845
 int foo(xxx); // expected-error{{unknown type name}}
+
+struct cls {
+  char *m;
+};
+
+char * cls::* __uptr wrong2 = &cls::m; // expected-error {{'__uptr' attribute cannot be used with pointers to members}}

Modified: cfe/trunk/test/Sema/MicrosoftExtensions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftExtensions.c?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/test/Sema/MicrosoftExtensions.c (original)
+++ cfe/trunk/test/Sema/MicrosoftExtensions.c Wed May 22 18:25:32 2013
@@ -102,3 +102,32 @@ void test( void ) {
 
 	enum DE1 no;	// no warning because E1 is not deprecated
 }
+
+int __sptr wrong1; // expected-error {{'__sptr' attribute only applies to pointer arguments}}
+// The modifier must follow the asterisk
+int __sptr *wrong_psp; // expected-error {{'__sptr' attribute only applies to pointer arguments}}
+int * __sptr __uptr wrong2; // expected-error {{'__sptr' and '__uptr' attributes are not compatible}}
+int * __sptr __sptr wrong3; // expected-warning {{attribute '__sptr' is already applied}}
+
+// It is illegal to overload based on the type attribute.
+void ptr_func(int * __ptr32 i) {}  // expected-note {{previous definition is here}}
+void ptr_func(int * __ptr64 i) {} // expected-error {{redefinition of 'ptr_func'}}
+
+// It is also illegal to overload based on the pointer type attribute.
+void ptr_func2(int * __sptr __ptr32 i) {}  // expected-note {{previous definition is here}}
+void ptr_func2(int * __uptr __ptr32 i) {} // expected-error {{redefinition of 'ptr_func2'}}
+
+int * __sptr __ptr32 __sptr wrong4; // expected-warning {{attribute '__sptr' is already applied}}
+
+__ptr32 int *wrong5; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+int *wrong6 __ptr32;  // expected-error {{expected ';' after top level declarator}} expected-warning {{declaration does not declare anything}}
+
+int * __ptr32 __ptr64 wrong7;  // expected-error {{'__ptr32' and '__ptr64' attributes are not compatible}}
+
+int * __ptr32 __ptr32 wrong8;	// expected-warning {{attribute '__ptr32' is already applied}}
+
+int *(__ptr32 __sptr wrong9); // expected-error {{'__sptr' attribute only applies to pointer arguments}} // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+typedef int *T;
+T __ptr32 wrong10; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}

Modified: cfe/trunk/test/Sema/attr-print.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-print.c?rev=182535&r1=182534&r2=182535&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-print.c (original)
+++ cfe/trunk/test/Sema/attr-print.c Wed May 22 18:25:32 2013
@@ -13,9 +13,22 @@ void foo() __attribute__((const));
 // CHECK: void bar() __attribute__((__const));
 void bar() __attribute__((__const));
 
-// FIXME: Print these at a valid location for these attributes.
-// CHECK: int *p32 __ptr32;
+// CHECK: int * __ptr32 p32;
 int * __ptr32 p32;
 
-// CHECK: int *p64 __ptr64;
+// CHECK: int * __ptr64 p64;
 int * __ptr64 p64;
+
+// TODO: the Type Printer has no way to specify the order to print attributes
+// in, and so it currently always prints them in reverse order. Fix this.
+// CHECK: int * __ptr32 __uptr p32_2;
+int * __uptr __ptr32 p32_2;
+
+// CHECK: int * __ptr64 __sptr p64_2;
+int * __sptr __ptr64 p64_2;
+
+// CHECK: int * __ptr32 __uptr p32_3;
+int * __uptr __ptr32 p32_3;
+
+// CHECK: int * __sptr * __ptr32 ppsp32;
+int * __sptr * __ptr32 ppsp32;





More information about the cfe-commits mailing list