diff options
Diffstat (limited to 'lib')
28 files changed, 598 insertions, 26 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 9505d299ab..36044826e8 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1293,7 +1293,7 @@ bool NamedDecl::isCXXInstanceMember() const { 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(ASTContext &C, unsigned ID) { 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, diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index bd6d99cd59..3f23f3d855 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -493,6 +493,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case NonTypeTemplateParm: case ObjCMethod: case ObjCProperty: + case MSProperty: return IDNS_Ordinary; case Label: return IDNS_Label; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index b97f4d1d3a..748d3084fe 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2789,6 +2789,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return false; case CallExprClass: + case MSPropertyRefExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 61bc3e2de5..c2a35f42c1 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // 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. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index d499228af3..3675b2ff44 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -6488,6 +6488,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXDynamicCastExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: + case Expr::MSPropertyRefExprClass: case Expr::CXXNullPtrLiteralExprClass: case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 0f4881e24e..0edad3e017 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -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. diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 7df7fdb92b..a86159f49d 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1238,6 +1238,18 @@ void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { 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: diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index bfd3132506..5525018f79 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -766,6 +766,11 @@ void StmtProfiler::VisitCXXUuidofExpr(const CXXUuidofExpr *S) { 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()); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 8865399b70..15bb6a6e45 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -45,6 +45,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::CXXDestructor: case Decl::CXXConversion: case Decl::Field: + case Decl::MSProperty: case Decl::IndirectField: case Decl::ObjCIvar: case Decl::ObjCAtDefsField: diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 55e2b38271..0094e13d4c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -394,17 +394,119 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, // 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 diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index e227d4e840..9ac4c63e19 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -23,6 +23,8 @@ size_t AttributeList::allocated_size() const { if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; else if (IsTypeTagForDatatype) return AttributeFactory::TypeTagForDatatypeAllocSize; + else if (IsProperty) + return AttributeFactory::PropertyAllocSize; return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1fc1a7cc48..44d0dde0db 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4889,6 +4889,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, break; // Microsoft attributes: + case AttributeList::AT_MsProperty: break; case AttributeList::AT_MsStruct: handleMsStructAttr(S, D, Attr); break; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8e8ea01395..a318f64765 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1603,6 +1603,13 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { 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, AccessSpecifier AS, Declarator &D, 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(CUDAFunctionTarget CallerTarget, 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; +} diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 26c3d354c7..4758718006 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -1111,6 +1111,9 @@ CanThrowResult Sema::canThrow(const Expr *E) { // 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) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index cafc42daa8..8ddc87af53 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2636,6 +2636,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, 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(SourceLocation CallLoc, /// 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, SourceLocation LParenLoc, 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, SourceLocation LParenLoc, 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. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3f2cb02673..cfc00502c4 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1170,6 +1170,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, 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 diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 847db24632..c3642f56ce 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -105,7 +105,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, 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::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, 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 *BaseExpr, QualType BaseExprType, 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]). diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index cd59a328f0..5a5fd26835 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4136,6 +4136,21 @@ InitializationSequence::InitializationSequence(Sema &S, : 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::InitializationSequence(Sema &S, // 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) { diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index b135507b1a..560efa5a4e 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -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::buildSet(Expr *op, SourceLocation opcLoc, } //===----------------------------------------------------------------------===// +// 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(); |