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