r179585 - Basic support for Microsoft property declarations and
John McCall
rjmccall at apple.com
Tue Apr 16 00:28:32 PDT 2013
Author: rjmccall
Date: Tue Apr 16 02:28:30 2013
New Revision: 179585
URL: http://llvm.org/viewvc/llvm-project?rev=179585&view=rev
Log:
Basic support for Microsoft property declarations and
references thereto.
Patch by Tong Shen!
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DeclNodes.td
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Basic/StmtNodes.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Sema/Template.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprClassification.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/AttributeList.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaExprMember.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaPseudoObject.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTCommon.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Parser/MicrosoftExtensions.cpp
cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
cfe/trunk/test/SemaObjC/property-user-setter.m
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CXCursor.cpp
cfe/trunk/tools/libclang/IndexBody.cpp
cfe/trunk/tools/libclang/IndexDecl.cpp
cfe/trunk/tools/libclang/IndexingContext.cpp
cfe/trunk/tools/libclang/IndexingContext.h
cfe/trunk/tools/libclang/RecursiveASTVisitor.h
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Apr 16 02:28:30 2013
@@ -2984,6 +2984,56 @@ public:
friend class ASTDeclReader;
};
+/// An instance of this class represents the declaration of a property
+/// member. This is a Microsoft extension to C++, first introduced in
+/// Visual Studio .NET 2003 as a parallel to similar features in C#
+/// and Managed C++.
+///
+/// A property must always be a non-static class member.
+///
+/// A property member superficially resembles a non-static data
+/// member, except preceded by a property attribute:
+/// __declspec(property(get=GetX, put=PutX)) int x;
+/// Either (but not both) of the 'get' and 'put' names may be omitted.
+///
+/// A reference to a property is always an lvalue. If the lvalue
+/// undergoes lvalue-to-rvalue conversion, then a getter name is
+/// required, and that member is called with no arguments.
+/// If the lvalue is assigned into, then a setter name is required,
+/// and that member is called with one argument, the value assigned.
+/// Both operations are potentially overloaded. Compound assignments
+/// are permitted, as are the increment and decrement operators.
+///
+/// The getter and putter methods are permitted to be overloaded,
+/// although their return and parameter types are subject to certain
+/// restrictions according to the type of the property.
+///
+/// A property declared using an incomplete array type may
+/// additionally be subscripted, adding extra parameters to the getter
+/// and putter methods.
+class MSPropertyDecl : public DeclaratorDecl {
+ IdentifierInfo *GetterId, *SetterId;
+
+public:
+ MSPropertyDecl(DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ SourceLocation StartL, IdentifierInfo *Getter,
+ IdentifierInfo *Setter):
+ DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterId(Getter),
+ SetterId(Setter) {}
+
+ static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
+
+ bool hasGetter() const { return GetterId != NULL; }
+ IdentifierInfo* getGetterId() const { return GetterId; }
+ bool hasSetter() const { return SetterId != NULL; }
+ IdentifierInfo* getSetterId() const { return SetterId; }
+
+ friend class ASTDeclReader;
+};
+
/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Apr 16 02:28:30 2013
@@ -29,6 +29,7 @@ class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
class CXXTemporary;
+class MSPropertyDecl;
class TemplateArgumentListInfo;
class UuidAttr;
@@ -560,6 +561,64 @@ public:
}
};
+/// A member reference to an MSPropertyDecl. This expression always
+/// has pseudo-object type, and therefore it is typically not
+/// encountered in a fully-typechecked expression except within the
+/// syntactic form of a PseudoObjectExpr.
+class MSPropertyRefExpr : public Expr {
+ Expr *BaseExpr;
+ MSPropertyDecl *TheDecl;
+ SourceLocation MemberLoc;
+ bool IsArrow;
+ NestedNameSpecifierLoc QualifierLoc;
+
+public:
+ MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
+ QualType ty, ExprValueKind VK,
+ NestedNameSpecifierLoc qualifierLoc,
+ SourceLocation nameLoc)
+ : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
+ /*type-dependent*/ false, baseExpr->isValueDependent(),
+ baseExpr->isInstantiationDependent(),
+ baseExpr->containsUnexpandedParameterPack()),
+ BaseExpr(baseExpr), TheDecl(decl),
+ MemberLoc(nameLoc), IsArrow(isArrow),
+ QualifierLoc(qualifierLoc) {}
+
+ MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getLocStart(), getLocEnd());
+ }
+ bool isImplicitAccess() const {
+ return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
+ }
+ SourceLocation getLocStart() const {
+ if (!isImplicitAccess())
+ return BaseExpr->getLocStart();
+ else if (QualifierLoc)
+ return QualifierLoc.getBeginLoc();
+ else
+ return MemberLoc;
+ }
+ SourceLocation getLocEnd() const { return getMemberLoc(); }
+
+ child_range children() {
+ return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSPropertyRefExprClass;
+ }
+
+ Expr *getBaseExpr() const { return BaseExpr; }
+ MSPropertyDecl *getPropertyDecl() const { return TheDecl; }
+ bool isArrow() const { return IsArrow; }
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ friend class ASTStmtReader;
+};
+
/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
/// the _GUID that corresponds to the supplied type or expression.
///
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Apr 16 02:28:30 2013
@@ -1671,6 +1671,10 @@ bool RecursiveASTVisitor<Derived>::Trave
return true;
}
+DEF_TRAVERSE_DECL(MSPropertyDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ })
+
DEF_TRAVERSE_DECL(FieldDecl, {
TRY_TO(TraverseDeclaratorHelper(D));
if (D->isBitField())
@@ -2058,6 +2062,10 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
+DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+})
+
DEF_TRAVERSE_STMT(CXXUuidofExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Apr 16 02:28:30 2013
@@ -928,6 +928,10 @@ def TypeTagForDatatype : InheritableAttr
// Microsoft-related attributes
+def MsProperty : Attr {
+ let Spellings = [Declspec<"property">];
+}
+
def MsStruct : InheritableAttr {
let Spellings = [Declspec<"ms_struct">];
}
Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Apr 16 02:28:30 2013
@@ -34,14 +34,15 @@ def Named : Decl<1>;
def UnresolvedUsingValue : DDecl<Value>;
def IndirectField : DDecl<Value>;
def Declarator : DDecl<Value, 1>;
+ def Field : DDecl<Declarator>;
+ def ObjCIvar : DDecl<Field>;
+ def ObjCAtDefsField : DDecl<Field>;
+ def MSProperty : DDecl<Declarator>;
def Function : DDecl<Declarator>, DeclContext;
def CXXMethod : DDecl<Function>;
def CXXConstructor : DDecl<CXXMethod>;
def CXXDestructor : DDecl<CXXMethod>;
def CXXConversion : DDecl<CXXMethod>;
- def Field : DDecl<Declarator>;
- def ObjCIvar : DDecl<Field>;
- def ObjCAtDefsField : DDecl<Field>;
def Var : DDecl<Declarator>;
def ImplicitParam : DDecl<Var>;
def ParmVar : DDecl<Var>;
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Apr 16 02:28:30 2013
@@ -527,6 +527,22 @@ def err_ms_declspec_type : Error<
"__declspec attributes must be an identifier or string literal">;
def warn_ms_declspec_unknown : Warning<
"unknown __declspec attribute %0 ignored">, InGroup<UnknownAttributes>;
+def err_ms_property_no_getter_or_putter : Error<
+ "property does not specify a getter or a putter">;
+def err_ms_property_unknown_accessor : Error<
+ "expected 'get' or 'put' in property declaration">;
+def err_ms_property_has_set_accessor : Error<
+ "putter for property must be specified as 'put', not 'set'">;
+def err_ms_property_missing_accessor_kind : Error<
+ "missing 'get=' or 'put='">;
+def err_ms_property_expected_equal : Error<
+ "expected '=' after '%0'">;
+def err_ms_property_duplicate_accessor : Error<
+ "property declaration specifies '%0' accessor twice">;
+def err_ms_property_expected_accessor_name : Error<
+ "expected name of accessor method">;
+def err_ms_property_expected_comma_or_rparen : Error<
+ "expected ',' or ')' at end of property accessor list">;
/// C++ Templates
def err_expected_template : Error<"expected template">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 16 02:28:30 2013
@@ -1810,6 +1810,19 @@ def err_attribute_section_local_variable
def warn_mismatched_section : Warning<
"section does not match previous declaration">, InGroup<Section>;
+def err_anonymous_property: Error<
+ "anonymous property is not supported">;
+def err_property_is_variably_modified: Error<
+ "property '%0' has a variably modified type">;
+def err_no_getter_for_property : Error<
+ "no getter defined for property '%0'">;
+def err_no_setter_for_property : Error<
+ "no setter defined for property '%0'">;
+def error_cannot_find_suitable_getter : Error<
+ "cannot find suitable getter for property '%0'">;
+def error_cannot_find_suitable_setter : Error<
+ "cannot find suitable setter for property '%0'">;
+
def err_attribute_aligned_not_power_of_two : Error<
"requested alignment is not a power of 2">;
def err_attribute_aligned_greater_than_8192 : Error<
Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Apr 16 02:28:30 2013
@@ -163,6 +163,7 @@ def BlockExpr : DStmt<Expr>;
def OpaqueValueExpr : DStmt<Expr>;
// Microsoft Extensions.
+def MSPropertyRefExpr : DStmt<Expr>;
def CXXUuidofExpr : DStmt<Expr>;
def SEHTryStmt : Stmt;
def SEHExceptStmt : Stmt;
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Apr 16 02:28:30 2013
@@ -96,6 +96,10 @@ private:
/// type_tag_for_datatype attribute.
unsigned IsTypeTagForDatatype : 1;
+ /// True if this has extra information associated with a
+ /// Microsoft __delcspec(property) attribute.
+ unsigned IsProperty : 1;
+
unsigned AttrKind : 8;
/// \brief The location of the 'unavailable' keyword in an
@@ -134,6 +138,11 @@ public:
unsigned LayoutCompatible : 1;
unsigned MustBeNull : 1;
};
+ struct PropertyData {
+ IdentifierInfo *GetterId, *SetterId;
+ PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
+ : GetterId(getterId), SetterId(setterId) {}
+ };
private:
TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
@@ -152,6 +161,16 @@ private:
return *reinterpret_cast<const ParsedType *>(this + 1);
}
+ PropertyData &getPropertyDataBuffer() {
+ assert(IsProperty);
+ return *reinterpret_cast<PropertyData*>(this + 1);
+ }
+
+ const PropertyData &getPropertyDataBuffer() const {
+ assert(IsProperty);
+ return *reinterpret_cast<const PropertyData*>(this + 1);
+ }
+
AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
void operator delete(void *) LLVM_DELETED_FUNCTION;
@@ -169,7 +188,8 @@ private:
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
+ IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
+ NextInPool(0) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -188,7 +208,7 @@ private:
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(),
NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
- IsTypeTagForDatatype(false),
+ IsTypeTagForDatatype(false), IsProperty(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
NextInPosition(0), NextInPool(0) {
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
@@ -208,7 +228,8 @@ private:
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
+ IsTypeTagForDatatype(true), IsProperty(false), NextInPosition(NULL),
+ NextInPool(NULL) {
TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
new (&ExtraData.MatchingCType) ParsedType(matchingCType);
ExtraData.LayoutCompatible = layoutCompatible;
@@ -225,11 +246,28 @@ private:
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
+ IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
+ NextInPool(0) {
new (&getTypeBuffer()) ParsedType(typeArg);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
+ /// Constructor for microsoft __declspec(property) attribute.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *parmName, SourceLocation parmLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
+ AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
+ SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(true), NextInPosition(0),
+ NextInPool(0) {
+ new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
friend class AttributePool;
friend class AttributeFactory;
@@ -253,6 +291,11 @@ public:
IdentifierInfo *getParameterName() const { return ParmName; }
SourceLocation getParameterLoc() const { return ParmLoc; }
+ /// Is this the Microsoft __declspec(property) attribute?
+ bool isDeclspecPropertyAttribute() const {
+ return IsProperty;
+ }
+
bool isAlignasAttribute() const {
// FIXME: Use a better mechanism to determine this.
return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword;
@@ -379,6 +422,11 @@ public:
return getTypeBuffer();
}
+ const PropertyData &getPropertyData() const {
+ assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer();
+ }
+
/// \brief Get an index into the attribute spelling list
/// defined in Attr.td. This index is used by an attribute
/// to pretty print itself.
@@ -402,6 +450,10 @@ public:
TypeTagForDatatypeAllocSize =
sizeof(AttributeList)
+ (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
+ / sizeof(void*) * sizeof(void*),
+ PropertyAllocSize =
+ sizeof(AttributeList)
+ + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
/ sizeof(void*) * sizeof(void*)
};
@@ -548,6 +600,20 @@ public:
parmName, parmLoc,
typeArg, syntaxUsed));
}
+
+ AttributeList *createPropertyAttribute(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *parmName, SourceLocation parmLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ AttributeList::Syntax syntaxUsed) {
+ void *memory = allocate(AttributeFactory::PropertyAllocSize);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ parmName, parmLoc,
+ getterId, setterId,
+ syntaxUsed));
+ }
};
/// addAttributeLists - Add two AttributeLists together
@@ -702,6 +768,21 @@ public:
add(attr);
return attr;
}
+
+ /// Add microsoft __delspec(property) attribute.
+ AttributeList *
+ addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *parmName, SourceLocation parmLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ AttributeList::Syntax syntaxUsed) {
+ AttributeList *attr =
+ pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
+ parmName, parmLoc, getterId, setterId,
+ syntaxUsed);
+ add(attr);
+ return attr;
+ }
AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
SourceLocation loc, int arg) {
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 16 02:28:30 2013
@@ -1586,6 +1586,12 @@ public:
Declarator &D, Expr *BitfieldWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS);
+ MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+ SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS,
+ AttributeList *MSPropertyAttr);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Tue Apr 16 02:28:30 2013
@@ -401,6 +401,7 @@ namespace clang {
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
+ Decl *VisitMSPropertyDecl(MSPropertyDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Apr 16 02:28:30 2013
@@ -951,6 +951,8 @@ namespace clang {
DECL_OBJC_PROPERTY_IMPL,
/// \brief A FieldDecl record.
DECL_FIELD,
+ /// \brief A MSPropertyDecl record.
+ DECL_MS_PROPERTY,
/// \brief A VarDecl record.
DECL_VAR,
/// \brief An ImplicitParamDecl record.
@@ -1300,6 +1302,7 @@ namespace clang {
EXPR_ASTYPE, // AsTypeExpr
// Microsoft
+ EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
STMT_SEH_EXCEPT, // SEHExceptStmt
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Apr 16 02:28:30 2013
@@ -1293,7 +1293,7 @@ bool NamedDecl::isCXXInstanceMember() co
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
+ if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
return true;
if (isa<CXXMethodDecl>(D))
return cast<CXXMethodDecl>(D)->isInstance();
@@ -3226,6 +3226,14 @@ BlockDecl *BlockDecl::CreateDeserialized
return new (Mem) BlockDecl(0, SourceLocation());
}
+MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(MSPropertyDecl));
+ return new (Mem) MSPropertyDecl(0, SourceLocation(), DeclarationName(),
+ QualType(), 0, SourceLocation(),
+ 0, 0);
+}
+
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
SourceLocation L,
IdentifierInfo *Id, QualType T,
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Apr 16 02:28:30 2013
@@ -493,6 +493,7 @@ unsigned Decl::getIdentifierNamespaceFor
case NonTypeTemplateParm:
case ObjCMethod:
case ObjCProperty:
+ case MSProperty:
return IDNS_Ordinary;
case Label:
return IDNS_Label;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Apr 16 02:28:30 2013
@@ -2789,6 +2789,7 @@ bool Expr::HasSideEffects(const ASTConte
return false;
case CallExprClass:
+ case MSPropertyRefExprClass:
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Apr 16 02:28:30 2013
@@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
// FIXME: ObjC++0x might have different rules
case Expr::ObjCIvarRefExprClass:
case Expr::FunctionParmPackExprClass:
+ case Expr::MSPropertyRefExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Apr 16 02:28:30 2013
@@ -6488,6 +6488,7 @@ static ICEDiag CheckICE(const Expr* E, A
case Expr::CXXDynamicCastExprClass:
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
+ case Expr::MSPropertyRefExprClass:
case Expr::CXXNullPtrLiteralExprClass:
case Expr::UserDefinedLiteralClass:
case Expr::CXXThisExprClass:
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Apr 16 02:28:30 2013
@@ -2394,6 +2394,7 @@ recurse:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
+ case Expr::MSPropertyRefExprClass:
llvm_unreachable("unexpected statement kind");
// FIXME: invent manglings for all these.
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Apr 16 02:28:30 2013
@@ -1238,6 +1238,18 @@ void StmtPrinter::VisitCXXUuidofExpr(CXX
OS << ")";
}
+void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
+ PrintExpr(Node->getBaseExpr());
+ if (Node->isArrow())
+ OS << "->";
+ else
+ OS << ".";
+ if (NestedNameSpecifier *Qualifier =
+ Node->getQualifierLoc().getNestedNameSpecifier())
+ Qualifier->print(OS, Policy);
+ OS << Node->getPropertyDecl()->getDeclName();
+}
+
void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
switch (Node->getLiteralOperatorKind()) {
case UserDefinedLiteral::LOK_Raw:
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Apr 16 02:28:30 2013
@@ -766,6 +766,11 @@ void StmtProfiler::VisitCXXUuidofExpr(co
VisitType(S->getTypeOperand());
}
+void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getPropertyDecl());
+}
+
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isImplicit());
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Apr 16 02:28:30 2013
@@ -45,6 +45,7 @@ void CodeGenFunction::EmitDecl(const Dec
case Decl::CXXDestructor:
case Decl::CXXConversion:
case Decl::Field:
+ case Decl::MSProperty:
case Decl::IndirectField:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Apr 16 02:28:30 2013
@@ -394,17 +394,119 @@ void Parser::ParseComplexMicrosoftDeclSp
// The property declspec is more complex in that it can take one or two
// assignment expressions as a parameter, but the lhs of the assignment
// must be named get or put.
- //
- // For right now, we will just skip to the closing right paren of the
- // property expression.
- //
- // FIXME: we should deal with __declspec(property) at some point because it
- // is used in the platform SDK headers for the Parallel Patterns Library
- // and ATL.
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- Ident->getNameStart(), tok::r_paren))
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_expected_lparen_after)
+ << Ident->getNameStart();
return;
+ }
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.expectAndConsume(diag::err_expected_lparen_after,
+ Ident->getNameStart(), tok::r_paren);
+
+ enum AccessorKind {
+ AK_Invalid = -1,
+ AK_Put = 0, AK_Get = 1 // indices into AccessorNames
+ };
+ IdentifierInfo *AccessorNames[] = { 0, 0 };
+ bool HasInvalidAccessor = false;
+
+ // Parse the accessor specifications.
+ while (true) {
+ // Stop if this doesn't look like an accessor spec.
+ if (!Tok.is(tok::identifier)) {
+ // If the user wrote a completely empty list, use a special diagnostic.
+ if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
+ AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) {
+ Diag(Loc, diag::err_ms_property_no_getter_or_putter);
+ break;
+ }
+
+ Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);
+ break;
+ }
+
+ AccessorKind Kind;
+ SourceLocation KindLoc = Tok.getLocation();
+ StringRef KindStr = Tok.getIdentifierInfo()->getName();
+ if (KindStr == "get") {
+ Kind = AK_Get;
+ } else if (KindStr == "put") {
+ Kind = AK_Put;
+
+ // Recover from the common mistake of using 'set' instead of 'put'.
+ } else if (KindStr == "set") {
+ Diag(KindLoc, diag::err_ms_property_has_set_accessor)
+ << FixItHint::CreateReplacement(KindLoc, "put");
+ Kind = AK_Put;
+
+ // Handle the mistake of forgetting the accessor kind by skipping
+ // this accessor.
+ } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
+ Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
+ ConsumeToken();
+ HasInvalidAccessor = true;
+ goto next_property_accessor;
+
+ // Otherwise, complain about the unknown accessor kind.
+ } else {
+ Diag(KindLoc, diag::err_ms_property_unknown_accessor);
+ HasInvalidAccessor = true;
+ Kind = AK_Invalid;
+
+ // Try to keep parsing unless it doesn't look like an accessor spec.
+ if (!NextToken().is(tok::equal)) break;
+ }
+
+ // Consume the identifier.
+ ConsumeToken();
+
+ // Consume the '='.
+ if (Tok.is(tok::equal)) {
+ ConsumeToken();
+ } else {
+ Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
+ << KindStr;
+ break;
+ }
+
+ // Expect the method name.
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);
+ break;
+ }
+
+ if (Kind == AK_Invalid) {
+ // Just drop invalid accessors.
+ } else if (AccessorNames[Kind] != NULL) {
+ // Complain about the repeated accessor, ignore it, and keep parsing.
+ Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
+ } else {
+ AccessorNames[Kind] = Tok.getIdentifierInfo();
+ }
+ ConsumeToken();
+
+ next_property_accessor:
+ // Keep processing accessors until we run out.
+ if (Tok.is(tok::comma)) {
+ ConsumeAnyToken();
+ continue;
+
+ // If we run into the ')', stop without consuming it.
+ } else if (Tok.is(tok::r_paren)) {
+ break;
+ } else {
+ Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
+ break;
+ }
+ }
+
+ // Only add the property attribute if it was well-formed.
+ if (!HasInvalidAccessor) {
+ Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), 0,
+ SourceLocation(),
+ AccessorNames[AK_Get], AccessorNames[AK_Put],
+ AttributeList::AS_Declspec);
+ }
T.skipToEnd();
} else {
// We don't recognize this as a valid declspec, but instead of creating the
Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Tue Apr 16 02:28:30 2013
@@ -23,6 +23,8 @@ size_t AttributeList::allocated_size() c
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
else if (IsTypeTagForDatatype)
return AttributeFactory::TypeTagForDatatypeAllocSize;
+ else if (IsProperty)
+ return AttributeFactory::PropertyAllocSize;
return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
}
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Apr 16 02:28:30 2013
@@ -4889,6 +4889,7 @@ static void ProcessInheritableDeclAttr(S
break;
// Microsoft attributes:
+ case AttributeList::AT_MsProperty: break;
case AttributeList::AT_MsStruct:
handleMsStructAttr(S, D, Attr);
break;
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Apr 16 02:28:30 2013
@@ -1603,6 +1603,13 @@ static bool InitializationHasSideEffects
return false;
}
+static AttributeList *getMSPropertyAttr(AttributeList *list) {
+ for (AttributeList* it = list; it != 0; it = it->getNext())
+ if (it->isDeclspecPropertyAttribute())
+ return it;
+ return 0;
+}
+
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
/// bitfield width if there is one, 'InitExpr' specifies the initializer if
@@ -1782,8 +1789,16 @@ Sema::ActOnCXXMemberDeclarator(Scope *S,
SS.clear();
}
- Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
- InitStyle, AS);
+ AttributeList *MSPropertyAttr =
+ getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
+ if (MSPropertyAttr) {
+ Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
+ BitWidth, InitStyle, AS, MSPropertyAttr);
+ isInstField = false;
+ } else {
+ Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
+ BitWidth, InitStyle, AS);
+ }
assert(Member && "HandleField never returns null");
} else {
assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
@@ -12096,3 +12111,94 @@ bool Sema::CheckCUDATarget(CUDAFunctionT
return false;
}
+
+/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
+///
+MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
+ SourceLocation DeclStart,
+ Declarator &D, Expr *BitWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS,
+ AttributeList *MSPropertyAttr) {
+ IdentifierInfo *II = D.getIdentifier();
+ if (!II) {
+ Diag(DeclStart, diag::err_anonymous_property);
+ return NULL;
+ }
+ SourceLocation Loc = D.getIdentifierLoc();
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
+ if (getLangOpts().CPlusPlus) {
+ CheckExtraCXXDefaultArguments(D);
+
+ if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_DataMemberType)) {
+ D.setInvalidType();
+ T = Context.IntTy;
+ TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+ }
+ }
+
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
+
+ if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_invalid_thread)
+ << DeclSpec::getSpecifierName(TSCS);
+
+ // Check to see if this name was declared as a member previously
+ NamedDecl *PrevDecl = 0;
+ LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+ LookupName(Previous, S);
+ switch (Previous.getResultKind()) {
+ case LookupResult::Found:
+ case LookupResult::FoundUnresolvedValue:
+ PrevDecl = Previous.getAsSingle<NamedDecl>();
+ break;
+
+ case LookupResult::FoundOverloaded:
+ PrevDecl = Previous.getRepresentativeDecl();
+ break;
+
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::Ambiguous:
+ break;
+ }
+
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
+ if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
+ PrevDecl = 0;
+
+ SourceLocation TSSL = D.getLocStart();
+ MSPropertyDecl *NewPD;
+ const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
+ NewPD = new (Context) MSPropertyDecl(Record, Loc,
+ II, T, TInfo, TSSL,
+ Data.GetterId, Data.SetterId);
+ ProcessDeclAttributes(TUScope, NewPD, D);
+ NewPD->setAccess(AS);
+
+ if (NewPD->isInvalidDecl())
+ Record->setInvalidDecl();
+
+ if (D.getDeclSpec().isModulePrivateSpecified())
+ NewPD->setModulePrivate();
+
+ if (NewPD->isInvalidDecl() && PrevDecl) {
+ // Don't introduce NewFD into scope; there's already something
+ // with the same name in the same scope.
+ } else if (II) {
+ PushOnScopeChains(NewPD, S);
+ } else
+ Record->addDecl(NewPD);
+
+ return NewPD;
+}
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Apr 16 02:28:30 2013
@@ -1111,6 +1111,9 @@ CanThrowResult Sema::canThrow(const Expr
// These expressions can never throw.
return CT_Cannot;
+ case Expr::MSPropertyRefExprClass:
+ llvm_unreachable("Invalid class for expression");
+
#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
#define STMT_RANGE(Base, First, Last)
#define LAST_STMT_RANGE(BASE, FIRST, LAST)
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Apr 16 02:28:30 2013
@@ -2636,6 +2636,10 @@ Sema::BuildDeclarationNameExpr(const CXX
break;
}
+ case Decl::MSProperty:
+ valueKind = VK_LValue;
+ break;
+
case Decl::CXXMethod:
// If we're referring to a method with an __unknown_anytype
// result type, make the entire expression __unknown_anytype.
@@ -4023,6 +4027,63 @@ Sema::CheckStaticArrayArgument(SourceLoc
/// to have a function type.
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
+/// Is the given type a placeholder that we need to lower out
+/// immediately during argument processing?
+static bool isPlaceholderToRemoveAsArg(QualType type) {
+ // Placeholders are never sugared.
+ const BuiltinType *placeholder = dyn_cast<BuiltinType>(type);
+ if (!placeholder) return false;
+
+ switch (placeholder->getKind()) {
+ // Ignore all the non-placeholder types.
+#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
+#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
+#include "clang/AST/BuiltinTypes.def"
+ return false;
+
+ // We cannot lower out overload sets; they might validly be resolved
+ // by the call machinery.
+ case BuiltinType::Overload:
+ return false;
+
+ // Unbridged casts in ARC can be handled in some call positions and
+ // should be left in place.
+ case BuiltinType::ARCUnbridgedCast:
+ return false;
+
+ // Pseudo-objects should be converted as soon as possible.
+ case BuiltinType::PseudoObject:
+ return true;
+
+ // The debugger mode could theoretically but currently does not try
+ // to resolve unknown-typed arguments based on known parameter types.
+ case BuiltinType::UnknownAny:
+ return true;
+
+ // These are always invalid as call arguments and should be reported.
+ case BuiltinType::BoundMember:
+ case BuiltinType::BuiltinFn:
+ return true;
+ }
+ llvm_unreachable("bad builtin type kind");
+}
+
+/// Check an argument list for placeholders that we won't try to
+/// handle later.
+static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
+ // Apply this processing to all the arguments at once instead of
+ // dying at the first failure.
+ bool hasInvalid = false;
+ for (size_t i = 0, e = args.size(); i != e; i++) {
+ if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
+ ExprResult result = S.CheckPlaceholderExpr(args[i]);
+ if (result.isInvalid()) hasInvalid = true;
+ else args[i] = result.take();
+ }
+ }
+ return hasInvalid;
+}
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -4035,6 +4096,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn,
if (Result.isInvalid()) return ExprError();
Fn = Result.take();
+ if (checkArgsForPlaceholders(*this, ArgExprs))
+ return ExprError();
+
if (getLangOpts().CPlusPlus) {
// If this is a pseudo-destructor expression, build the call immediately.
if (isa<CXXPseudoDestructorExpr>(Fn)) {
@@ -4050,6 +4114,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn,
Context.VoidTy, VK_RValue,
RParenLoc));
}
+ if (Fn->getType() == Context.PseudoObjectTy) {
+ ExprResult result = CheckPlaceholderExpr(Fn);
+ if (result.isInvalid()) return ExprError();
+ Fn = result.take();
+ }
// Determine whether this is a dependent call inside a C++ template,
// in which case we won't do any semantic analysis now.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Apr 16 02:28:30 2013
@@ -1170,6 +1170,11 @@ Sema::BuildCXXNew(SourceRange Range, boo
QualType ResultType = Context.getPointerType(AllocType);
+ if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(ArraySize);
+ if (result.isInvalid()) return ExprError();
+ ArraySize = result.take();
+ }
// C++98 5.3.4p6: "The expression in a direct-new-declarator shall have
// integral or enumeration type with a non-negative value."
// C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped
Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Apr 16 02:28:30 2013
@@ -105,7 +105,8 @@ static IMAKind ClassifyImplicitMemberAcc
NamedDecl *D = *I;
if (D->isCXXInstanceMember()) {
- if (dyn_cast<FieldDecl>(D) || dyn_cast<IndirectFieldDecl>(D))
+ if (dyn_cast<FieldDecl>(D) || dyn_cast<MSPropertyDecl>(D)
+ || dyn_cast<IndirectFieldDecl>(D))
isField = true;
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
@@ -778,6 +779,19 @@ Sema::BuildAnonymousStructUnionMemberRef
return Owned(result);
}
+static ExprResult
+BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+ const CXXScopeSpec &SS,
+ MSPropertyDecl *PD,
+ const DeclarationNameInfo &NameInfo) {
+ // Property names are always simple identifiers and therefore never
+ // require any interesting additional storage.
+ return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
+ S.Context.PseudoObjectTy, VK_LValue,
+ SS.getWithLocInContext(S.Context),
+ NameInfo.getLoc());
+}
+
/// \brief Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(Sema &SemaRef,
ASTContext &C, Expr *Base, bool isArrow,
@@ -935,6 +949,10 @@ Sema::BuildMemberReferenceExpr(Expr *Bas
return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
SS, FD, FoundDecl, MemberNameInfo);
+ if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
+ return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
+ MemberNameInfo);
+
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Apr 16 02:28:30 2013
@@ -4136,6 +4136,21 @@ InitializationSequence::InitializationSe
: FailedCandidateSet(Kind.getLocation()) {
ASTContext &Context = S.Context;
+ // Eliminate non-overload placeholder types in the arguments. We
+ // need to do this before checking whether types are dependent
+ // because lowering a pseudo-object expression might well give us
+ // something of dependent type.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
+ // FIXME: should we be doing this here?
+ ExprResult result = S.CheckPlaceholderExpr(Args[I]);
+ if (result.isInvalid()) {
+ SetFailed(FK_PlaceholderType);
+ return;
+ }
+ Args[I] = result.take();
+ }
+
// C++0x [dcl.init]p16:
// The semantics of initializers are as follows. The destination type is
// the type of the object or reference being initialized and the source
@@ -4153,18 +4168,6 @@ InitializationSequence::InitializationSe
// Almost everything is a normal sequence.
setSequenceKind(NormalSequence);
- for (unsigned I = 0; I != NumArgs; ++I)
- if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
- // FIXME: should we be doing this here?
- ExprResult result = S.CheckPlaceholderExpr(Args[I]);
- if (result.isInvalid()) {
- SetFailed(FK_PlaceholderType);
- return;
- }
- Args[I] = result.take();
- }
-
-
QualType SourceType;
Expr *Initializer = 0;
if (NumArgs == 1) {
Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Apr 16 02:28:30 2013
@@ -153,6 +153,23 @@ namespace {
refExpr->getRBracket());
}
};
+
+ struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> {
+ Expr *NewBase;
+ MSPropertyRefRebuilder(Sema &S, Expr *newBase)
+ : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {}
+
+ typedef MSPropertyRefExpr specific_type;
+ Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) {
+ assert(refExpr->getBaseExpr());
+
+ return new (S.Context)
+ MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(),
+ refExpr->isArrow(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getQualifierLoc(),
+ refExpr->getMemberLoc());
+ }
+ };
class PseudoOpBuilder {
public:
@@ -284,6 +301,18 @@ namespace {
ExprResult buildSet(Expr *op, SourceLocation, bool);
};
+ class MSPropertyOpBuilder : public PseudoOpBuilder {
+ MSPropertyRefExpr *RefExpr;
+
+ public:
+ MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
+ PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ RefExpr(refExpr) {}
+
+ Expr *rebuildAndCaptureObject(Expr *);
+ ExprResult buildGet();
+ ExprResult buildSet(Expr *op, SourceLocation, bool);
+ };
}
/// Capture the given expression in an OpaqueValueExpr.
@@ -1324,6 +1353,77 @@ ExprResult ObjCSubscriptOpBuilder::build
}
//===----------------------------------------------------------------------===//
+// MSVC __declspec(property) references
+//===----------------------------------------------------------------------===//
+
+Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+ Expr *NewBase = capture(RefExpr->getBaseExpr());
+
+ syntacticBase =
+ MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase);
+
+ return syntacticBase;
+}
+
+ExprResult MSPropertyOpBuilder::buildGet() {
+ if (!RefExpr->getPropertyDecl()->hasGetter()) {
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property)
+ << RefExpr->getPropertyDecl()->getName();
+ return ExprError();
+ }
+
+ UnqualifiedId GetterName;
+ IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
+ GetterName.setIdentifier(II, RefExpr->getMemberLoc());
+ CXXScopeSpec SS;
+ SS.Adopt(RefExpr->getQualifierLoc());
+ ExprResult GetterExpr = S.ActOnMemberAccessExpr(
+ S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
+ GetterName, 0, true);
+ if (GetterExpr.isInvalid()) {
+ S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_getter)
+ << RefExpr->getPropertyDecl()->getName();
+ return ExprError();
+ }
+
+ MultiExprArg ArgExprs;
+ return S.ActOnCallExpr(S.getCurScope(), GetterExpr.take(),
+ RefExpr->getSourceRange().getBegin(), ArgExprs,
+ RefExpr->getSourceRange().getEnd());
+}
+
+ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
+ bool captureSetValueAsResult) {
+ if (!RefExpr->getPropertyDecl()->hasSetter()) {
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property)
+ << RefExpr->getPropertyDecl()->getName();
+ return ExprError();
+ }
+
+ UnqualifiedId SetterName;
+ IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
+ SetterName.setIdentifier(II, RefExpr->getMemberLoc());
+ CXXScopeSpec SS;
+ SS.Adopt(RefExpr->getQualifierLoc());
+ ExprResult SetterExpr = S.ActOnMemberAccessExpr(
+ S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
+ SetterName, 0, true);
+ if (SetterExpr.isInvalid()) {
+ S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_setter)
+ << RefExpr->getPropertyDecl()->getName();
+ return ExprError();
+ }
+
+ SmallVector<Expr*, 1> ArgExprs;
+ ArgExprs.push_back(op);
+ return S.ActOnCallExpr(S.getCurScope(), SetterExpr.take(),
+ RefExpr->getSourceRange().getBegin(), ArgExprs,
+ op->getSourceRange().getEnd());
+}
+
+//===----------------------------------------------------------------------===//
// General Sema routines.
//===----------------------------------------------------------------------===//
@@ -1338,6 +1438,10 @@ ExprResult Sema::checkPseudoObjectRValue
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
ObjCSubscriptOpBuilder builder(*this, refExpr);
return builder.buildRValueOperation(E);
+ } else if (MSPropertyRefExpr *refExpr
+ = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+ MSPropertyOpBuilder builder(*this, refExpr);
+ return builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1360,6 +1464,10 @@ ExprResult Sema::checkPseudoObjectIncDec
} else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
Diag(opcLoc, diag::err_illegal_container_subscripting_op);
return ExprError();
+ } else if (MSPropertyRefExpr *refExpr
+ = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+ MSPropertyOpBuilder builder(*this, refExpr);
+ return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1389,6 +1497,10 @@ ExprResult Sema::checkPseudoObjectAssign
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
ObjCSubscriptOpBuilder builder(*this, refExpr);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+ } else if (MSPropertyRefExpr *refExpr
+ = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+ MSPropertyOpBuilder builder(*this, refExpr);
+ return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1414,6 +1526,10 @@ static Expr *stripOpaqueValuesFromPseudo
OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
keyOVE->getSourceExpr()).rebuild(E);
+ } else if (MSPropertyRefExpr *refExpr
+ = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+ OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
+ return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 16 02:28:30 2013
@@ -525,6 +525,53 @@ Decl *TemplateDeclInstantiator::VisitFie
return Field;
}
+Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
+ bool Invalid = false;
+ TypeSourceInfo *DI = D->getTypeSourceInfo();
+
+ if (DI->getType()->isVariablyModifiedType()) {
+ SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified)
+ << D->getName();
+ Invalid = true;
+ } else if (DI->getType()->isInstantiationDependentType()) {
+ DI = SemaRef.SubstType(DI, TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI) {
+ DI = D->getTypeSourceInfo();
+ Invalid = true;
+ } else if (DI->getType()->isFunctionType()) {
+ // C++ [temp.arg.type]p3:
+ // If a declaration acquires a function type through a type
+ // dependent on a template-parameter and this causes a
+ // declaration that does not use the syntactic form of a
+ // function declarator to have function type, the program is
+ // ill-formed.
+ SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+ << DI->getType();
+ Invalid = true;
+ }
+ } else {
+ SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+ }
+
+ MSPropertyDecl *Property = new (SemaRef.Context)
+ MSPropertyDecl(Owner, D->getLocation(),
+ D->getDeclName(), DI->getType(), DI,
+ D->getLocStart(),
+ D->getGetterId(), D->getSetterId());
+
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs,
+ StartingScope);
+
+ if (Invalid)
+ Property->setInvalidDecl();
+
+ Property->setAccess(D->getAccess());
+ Owner->addDecl(Property);
+
+ return Property;
+}
+
Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
NamedDecl **NamedChain =
new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Apr 16 02:28:30 2013
@@ -6029,6 +6029,32 @@ TreeTransform<Derived>::TransformMSDepen
}
template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ NestedNameSpecifierLoc QualifierLoc;
+ if (E->getQualifierLoc()) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+ if (!QualifierLoc)
+ return ExprError();
+ }
+
+ MSPropertyDecl *PD = cast_or_null<MSPropertyDecl>(
+ getDerived().TransformDecl(E->getMemberLoc(), E->getPropertyDecl()));
+ if (!PD)
+ return ExprError();
+
+ ExprResult Base = getDerived().TransformExpr(E->getBaseExpr());
+ if (Base.isInvalid())
+ return ExprError();
+
+ return new (SemaRef.getASTContext())
+ MSPropertyRefExpr(Base.get(), PD, E->isArrow(),
+ SemaRef.getASTContext().PseudoObjectTy, VK_LValue,
+ QualifierLoc, E->getMemberLoc());
+}
+
+template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock());
Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Apr 16 02:28:30 2013
@@ -180,6 +180,7 @@ bool serialization::isRedeclarableDeclKi
case Decl::UnresolvedUsingValue:
case Decl::IndirectField:
case Decl::Field:
+ case Decl::MSProperty:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
case Decl::ImplicitParam:
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Apr 16 02:28:30 2013
@@ -244,6 +244,7 @@ namespace clang {
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
void VisitCXXConversionDecl(CXXConversionDecl *D);
void VisitFieldDecl(FieldDecl *FD);
+ void VisitMSPropertyDecl(MSPropertyDecl *FD);
void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
void VisitVarDecl(VarDecl *VD);
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
@@ -879,6 +880,12 @@ void ASTDeclReader::VisitFieldDecl(Field
}
}
+void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
+ VisitDeclaratorDecl(PD);
+ PD->GetterId = Reader.GetIdentifierInfo(F, Record, Idx);
+ PD->SetterId = Reader.GetIdentifierInfo(F, Record, Idx);
+}
+
void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
VisitValueDecl(FD);
@@ -2136,6 +2143,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
case DECL_BLOCK:
D = BlockDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_MS_PROPERTY:
+ D = MSPropertyDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
return 0;
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Apr 16 02:28:30 2013
@@ -1498,6 +1498,15 @@ void ASTStmtReader::VisitOpaqueValueExpr
//===----------------------------------------------------------------------===//
// Microsoft Expressions and Statements
//===----------------------------------------------------------------------===//
+void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ VisitExpr(E);
+ E->IsArrow = (Record[Idx++] != 0);
+ E->BaseExpr = Reader.ReadSubExpr();
+ E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ E->MemberLoc = ReadSourceLocation(Record, Idx);
+ E->TheDecl = ReadDeclAs<MSPropertyDecl>(Record, Idx);
+}
+
void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
VisitExpr(E);
E->setSourceRange(ReadSourceRange(Record, Idx));
@@ -2073,6 +2082,9 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
case EXPR_CXX_UUIDOF_EXPR:
S = new (Context) CXXUuidofExpr(Empty, true);
break;
+ case EXPR_CXX_PROPERTY_REF_EXPR:
+ S = new (Context) MSPropertyRefExpr(Empty);
+ break;
case EXPR_CXX_UUIDOF_TYPE:
S = new (Context) CXXUuidofExpr(Empty, false);
break;
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Apr 16 02:28:30 2013
@@ -907,6 +907,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_OBJC_PROPERTY);
RECORD(DECL_OBJC_PROPERTY_IMPL);
RECORD(DECL_FIELD);
+ RECORD(DECL_MS_PROPERTY);
RECORD(DECL_VAR);
RECORD(DECL_IMPLICIT_PARAM);
RECORD(DECL_PARM_VAR);
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Apr 16 02:28:30 2013
@@ -81,6 +81,7 @@ namespace clang {
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
void VisitCXXConversionDecl(CXXConversionDecl *D);
void VisitFieldDecl(FieldDecl *D);
+ void VisitMSPropertyDecl(MSPropertyDecl *D);
void VisitIndirectFieldDecl(IndirectFieldDecl *D);
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -662,6 +663,13 @@ void ASTDeclWriter::VisitFieldDecl(Field
Code = serialization::DECL_FIELD;
}
+void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) {
+ VisitDeclaratorDecl(D);
+ Writer.AddIdentifierRef(D->getGetterId(), Record);
+ Writer.AddIdentifierRef(D->getSetterId(), Record);
+ Code = serialization::DECL_MS_PROPERTY;
+}
+
void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
VisitValueDecl(D);
Record.push_back(D->getChainingSize());
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Apr 16 02:28:30 2013
@@ -1534,6 +1534,16 @@ void ASTStmtWriter::VisitAsTypeExpr(AsTy
//===----------------------------------------------------------------------===//
// Microsoft Expressions and Statements.
//===----------------------------------------------------------------------===//
+void ASTStmtWriter::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->isArrow());
+ Writer.AddStmt(E->getBaseExpr());
+ Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
+ Writer.AddSourceLocation(E->getMemberLoc(), Record);
+ Writer.AddDeclRef(E->getPropertyDecl(), Record);
+ Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR;
+}
+
void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
VisitExpr(E);
Writer.AddSourceRange(E->getSourceRange(), Record);
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Apr 16 02:28:30 2013
@@ -609,6 +609,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
case Stmt::CXXTryStmtClass:
case Stmt::CXXTypeidExprClass:
case Stmt::CXXUuidofExprClass:
+ case Stmt::MSPropertyRefExprClass:
case Stmt::CXXUnresolvedConstructExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::UnaryTypeTraitExprClass:
Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Tue Apr 16 02:28:30 2013
@@ -331,3 +331,32 @@ namespace Inheritance {
class __multiple_inheritance B;
class __virtual_inheritance C;
}
+
+struct StructWithProperty {
+ __declspec(property) int V0; // expected-error {{expected '(' after 'property'}}
+ __declspec(property()) int V1; // expected-error {{property does not specify a getter or a putter}}
+ __declspec(property(set)) int V2; // expected-error {{putter for property must be specified as 'put', not 'set'}} expected-error {{expected '=' after 'set'}}
+ __declspec(property(ptu)) int V3; // expected-error {{missing 'get=' or 'put='}}
+ __declspec(property(ptu=PutV)) int V4; // expected-error {{expected 'get' or 'put' in property declaration}}
+ __declspec(property(get)) int V5; // expected-error {{expected '=' after 'get'}}
+ __declspec(property(get&)) int V6; // expected-error {{expected '=' after 'get'}}
+ __declspec(property(get=)) int V7; // expected-error {{expected name of accessor method}}
+ __declspec(property(get=GetV)) int V8; // no-warning
+ __declspec(property(get=GetV=)) int V9; // expected-error {{expected ',' or ')' at end of property accessor list}}
+ __declspec(property(get=GetV,)) int V10; // expected-error {{expected 'get' or 'put' in property declaration}}
+ __declspec(property(get=GetV,put=SetV)) int V11; // no-warning
+ __declspec(property(get=GetV,put=SetV,get=GetV)) int V12; // expected-error {{property declaration specifies 'get' accessor twice}}
+
+ int GetV() { return 123; }
+ void SetV(int v) {}
+};
+void TestProperty() {
+ StructWithProperty sp;
+ sp.V8;
+ sp.V8 = 0; // expected-error {{no setter defined for property 'V8'}}
+ int i = sp.V11;
+ sp.V11 = i++;
+ sp.V11 += 8;
+ sp.V11++;
+ ++sp.V11;
+}
Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Tue Apr 16 02:28:30 2013
@@ -208,3 +208,127 @@ void ::f(); // expected-warning{{extra q
class C {
C::C(); // expected-warning{{extra qualification on member 'C'}}
};
+
+struct StructWithProperty {
+ __declspec(property(get=GetV)) int V1;
+ __declspec(property(put=SetV)) int V2;
+ __declspec(property(get=GetV, put=SetV_NotExist)) int V3;
+ __declspec(property(get=GetV_NotExist, put=SetV)) int V4;
+ __declspec(property(get=GetV, put=SetV)) int V5;
+
+ int GetV() { return 123; }
+ void SetV(int i) {}
+};
+void TestProperty() {
+ StructWithProperty sp;
+ int i = sp.V2; // expected-error{{no getter defined for property 'V2'}}
+ sp.V1 = 12; // expected-error{{no setter defined for property 'V1'}}
+ int j = sp.V4; // expected-error{{no member named 'GetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable getter for property 'V4'}}
+ sp.V3 = 14; // expected-error{{no member named 'SetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable setter for property 'V3'}}
+ int k = sp.V5;
+ sp.V5 = k++;
+}
+
+/* 4 tests for PseudoObject, begin */
+struct SP1
+{
+ bool operator()() { return true; }
+};
+struct SP2
+{
+ __declspec(property(get=GetV)) SP1 V;
+ SP1 GetV() { return SP1(); }
+};
+void TestSP2() {
+ SP2 sp2;
+ bool b = sp2.V();
+}
+
+struct SP3 {
+ template <class T>
+ void f(T t) {}
+};
+template <class T>
+struct SP4
+{
+ __declspec(property(get=GetV)) int V;
+ int GetV() { return 123; }
+ void f() { SP3 s2; s2.f(V); }
+};
+void TestSP4() {
+ SP4<int> s;
+ s.f();
+}
+
+template <class T>
+struct SP5
+{
+ __declspec(property(get=GetV)) T V;
+ int GetV() { return 123; }
+ void f() { int *p = new int[V]; }
+};
+
+template <class T>
+struct SP6
+{
+public:
+ __declspec(property(get=GetV)) T V;
+ T GetV() { return 123; }
+ void f() { int t = V; }
+};
+void TestSP6() {
+ SP6<int> c;
+ c.f();
+}
+/* 4 tests for PseudoObject, end */
+
+// Property access: explicit, implicit, with Qualifier
+struct SP7 {
+ __declspec(property(get=GetV, put=SetV)) int V;
+ int GetV() { return 123; }
+ void SetV(int v) {}
+
+ void ImplicitAccess() { int i = V; V = i; }
+ void ExplicitAccess() { int i = this->V; this->V = i; }
+};
+struct SP8: public SP7 {
+ void AccessWithQualifier() { int i = SP7::V; SP7::V = i; }
+};
+
+// Property usage
+template <class T>
+struct SP9 {
+ __declspec(property(get=GetV, put=SetV)) T V;
+ T GetV() { return 0; }
+ void SetV(T v) {}
+ void f() { V = this->V; V < this->V; }
+ //void g() { V++; }
+ //void h() { V*=2; }
+};
+struct SP10 {
+ SP10(int v) {}
+ bool operator<(const SP10& v) { return true; }
+ SP10 operator*(int v) { return *this; }
+ SP10& operator=(const SP10& v) { return *this; }
+};
+void TestSP9() {
+ SP9<int> c;
+ int i = c.V; // Decl initializer
+ i = c.V; // Binary op operand
+ c.SetV(c.V); // CallExpr arg
+ int *p = new int[c.V + 1]; // Array size
+ p[c.V] = 1; // Array index
+
+ c.V = 123; // Setter
+
+ c.V++; // Unary op operand
+ c.V *= 2; // Unary op operand
+
+ SP9<int*> c2;
+ c2.V[0] = 123; // Array
+
+ SP9<SP10> c3;
+ c3.f(); // Overloaded binary op operand
+ //c3.g(); // Overloaded incdec op operand
+ //c3.h(); // Overloaded unary op operand
+}
Modified: cfe/trunk/test/SemaObjC/property-user-setter.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-user-setter.m?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-user-setter.m (original)
+++ cfe/trunk/test/SemaObjC/property-user-setter.m Tue Apr 16 02:28:30 2013
@@ -85,7 +85,7 @@ static int g_val;
- (void)setFoo:(int)value;
@end
-void g(int); // expected-note {{passing argument to parameter here}}
+void g(int);
void f(C *c) {
c.Foo = 17; // OK
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Apr 16 02:28:30 2013
@@ -4458,6 +4458,7 @@ CXCursor clang_getCursorDefinition(CXCur
case Decl::TemplateTypeParm:
case Decl::EnumConstant:
case Decl::Field:
+ case Decl::MSProperty:
case Decl::IndirectField:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Apr 16 02:28:30 2013
@@ -442,6 +442,7 @@ CXCursor cxcursor::MakeCXCursor(const St
case Stmt::CXXDependentScopeMemberExprClass:
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::MemberExprClass:
+ case Stmt::MSPropertyRefExprClass:
case Stmt::ObjCIsaExprClass:
case Stmt::ObjCIvarRefExprClass:
case Stmt::ObjCPropertyRefExprClass:
Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Apr 16 02:28:30 2013
@@ -89,6 +89,12 @@ public:
return true;
}
+ bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
+ ParentDC, E, CXIdxEntityRef_Direct);
+ return true;
+ }
+
bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
Parent, ParentDC, E, CXIdxEntityRef_Direct);
Modified: cfe/trunk/tools/libclang/IndexDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexDecl.cpp (original)
+++ cfe/trunk/tools/libclang/IndexDecl.cpp Tue Apr 16 02:28:30 2013
@@ -105,6 +105,11 @@ public:
return true;
}
+ bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+ handleDeclarator(D);
+ return true;
+ }
+
bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
IndexCtx.handleEnumerator(D);
IndexCtx.indexBody(D->getInitExpr(), D);
Modified: cfe/trunk/tools/libclang/IndexingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexingContext.cpp (original)
+++ cfe/trunk/tools/libclang/IndexingContext.cpp Tue Apr 16 02:28:30 2013
@@ -396,6 +396,12 @@ bool IndexingContext::handleField(const
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
+bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
/*isContainer=*/false);
Modified: cfe/trunk/tools/libclang/IndexingContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexingContext.h (original)
+++ cfe/trunk/tools/libclang/IndexingContext.h Tue Apr 16 02:28:30 2013
@@ -16,6 +16,7 @@
namespace clang {
class FileEntry;
+ class MSPropertyDecl;
class ObjCPropertyDecl;
class ClassTemplateDecl;
class FunctionTemplateDecl;
@@ -404,6 +405,8 @@ public:
bool handleField(const FieldDecl *D);
+ bool handleMSProperty(const MSPropertyDecl *D);
+
bool handleEnumerator(const EnumConstantDecl *D);
bool handleTagDecl(const TagDecl *D);
Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original)
+++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Tue Apr 16 02:28:30 2013
@@ -1614,6 +1614,10 @@ DEF_TRAVERSE_DECL(FieldDecl, {
TRY_TO(TraverseStmt(D->getInClassInitializer()));
})
+DEF_TRAVERSE_DECL(MSPropertyDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ })
+
DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
TRY_TO(TraverseDeclaratorHelper(D));
if (D->isBitField())
@@ -2133,6 +2137,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr,
}
})
+DEF_TRAVERSE_STMT(MSPropertyRefExpr, {})
DEF_TRAVERSE_STMT(SEHTryStmt, {})
DEF_TRAVERSE_STMT(SEHExceptStmt, {})
DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
More information about the cfe-commits
mailing list