forked from OSchip/llvm-project
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. llvm-svn: 182535
This commit is contained in:
parent
81f43ae23a
commit
317a77f1c7
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1788,7 +1788,9 @@ def err_attribute_uuid_malformed_guid : Error<
|
|||
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>;
|
||||
|
|
|
@ -509,6 +509,8 @@ ALIAS("__volatile__" , volatile , KEYALL)
|
|||
// 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)
|
||||
|
|
|
@ -1072,6 +1072,17 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
|
|||
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(const AttributedType *T,
|
|||
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();
|
||||
|
|
|
@ -601,7 +601,8 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
|
|||
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(DeclSpec &DS,
|
|||
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 DisambiguatingWithExpression) {
|
|||
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(DeclSpec &DS,
|
|||
ParseOpenCLQualifiers(DS);
|
||||
break;
|
||||
|
||||
case tok::kw___sptr:
|
||||
case tok::kw___uptr:
|
||||
case tok::kw___w64:
|
||||
case tok::kw___ptr64:
|
||||
case tok::kw___ptr32:
|
||||
|
|
|
@ -1122,6 +1122,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
|||
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:
|
||||
|
|
|
@ -4252,7 +4252,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
|
|||
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 &S, Decl *D, const AttributeList &Attr) {
|
|||
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(Sema &S, Scope *scope, Decl *D,
|
|||
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(Sema &S, Scope *scope, Decl *D,
|
|||
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:
|
||||
|
|
|
@ -108,7 +108,14 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
|
|||
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(TypeProcessingState &state,
|
|||
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 distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
|
|||
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 getAttrListKind(AttributedType::Kind kind) {
|
|||
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(TypeProcessingState &state, QualType &type,
|
|||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue