diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 60 |
9 files changed, 127 insertions, 26 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 7cc436c7a90..46532cafae6 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -497,6 +497,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } case MemberExprClass: + case CXXQualifiedMemberExprClass: // If the base pointer or element is to a volatile pointer/field, accessing // it is a side effect. if (getType().isVolatileQualified()) @@ -684,7 +685,8 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; break; } - case MemberExprClass: { + case MemberExprClass: + case CXXQualifiedMemberExprClass: { const MemberExpr *m = cast<MemberExpr>(this); if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4: NamedDecl *Member = m->getMemberDecl(); @@ -948,7 +950,8 @@ bool Expr::hasGlobalStorage() const { return true; return false; } - case MemberExprClass: { + case MemberExprClass: + case CXXQualifiedMemberExprClass: { const MemberExpr *M = cast<MemberExpr>(this); return !M->isArrow() && M->getBase()->hasGlobalStorage(); } @@ -992,7 +995,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { } return false; } - case MemberExprClass: { + case MemberExprClass: + case CXXQualifiedMemberExprClass: { const MemberExpr *M = cast<MemberExpr>(this); return M->getBase()->isOBJCGCCandidate(Ctx); } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1c3041c8cdb..c9614e178c4 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1126,6 +1126,16 @@ StmtPrinter::VisitCXXUnresolvedConstructExpr( OS << ")"; } +void StmtPrinter::VisitCXXQualifiedMemberExpr(CXXQualifiedMemberExpr *Node) { + // FIXME: Suppress printing implicit bases (like "this") + PrintExpr(Node->getBase()); + OS << (Node->isArrow() ? "->" : "."); + // FIXME: Suppress printing references to unnamed objects + // representing anonymous unions/structs + Node->getQualifier()->print(OS, Policy); + OS << Node->getMemberDecl()->getNameAsString(); +} + void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) { PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index ff202991684..0ffe5e17c63 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -546,6 +546,11 @@ StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) { VisitType(S->getTypeAsWritten()); } +void StmtProfiler::VisitCXXQualifiedMemberExpr(CXXQualifiedMemberExpr *S) { + VisitMemberExpr(S); + VisitNestedNameSpecifier(S->getQualifier()); +} + void StmtProfiler::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *S) { VisitExpr(S); ID.AddBoolean(S->isArrow()); diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 3abaf552d8e..600c52c5b09 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -408,6 +408,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { break; case Stmt::MemberExprClass: + case Stmt::CXXQualifiedMemberExprClass: VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false); break; @@ -515,6 +516,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, return; case Stmt::MemberExprClass: + case Stmt::CXXQualifiedMemberExprClass: VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true); return; diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 5405ac07d9e..680d7357b9a 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -212,11 +212,13 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { This = BaseLV.getAddress(); } + // C++ [class.virtual]p12: + // Explicit qualification with the scope operator (5.1) suppresses the + // virtual call mechanism. llvm::Value *Callee; - // FIXME: Someone needs to keep track of the qualifications. - if (MD->isVirtual() /* && !ME->NotQualified() */) + if (MD->isVirtual() && !isa<CXXQualifiedMemberExpr>(CE)) { Callee = BuildVirtualCall(MD, This, Ty); - else + } else Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); return EmitCXXMemberCall(MD, Callee, This, diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 310fae03c63..75fc107d20e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -240,7 +240,9 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); case Expr::ExtVectorElementExprClass: return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E)); - case Expr::MemberExprClass: return EmitMemberExpr(cast<MemberExpr>(E)); + case Expr::MemberExprClass: + case Stmt::CXXQualifiedMemberExprClass: + return EmitMemberExpr(cast<MemberExpr>(E)); case Expr::CompoundLiteralExprClass: return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E)); case Expr::ConditionalOperatorClass: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 27f03bd98f4..e6fa3727369 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1421,7 +1421,8 @@ static DeclRefExpr* EvalVal(Expr *E) { } // Accesses to members are potential references to data on the stack. - case Stmt::MemberExprClass: { + case Stmt::MemberExprClass: + case Stmt::CXXQualifiedMemberExprClass: { MemberExpr *M = cast<MemberExpr>(E); // Check for indirect access. We only want direct field accesses. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7a8189835fb..e7370898189 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -631,6 +631,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, if (BaseAddrSpace != MemberType.getAddressSpace()) MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace); MarkDeclarationReferenced(Loc, *FI); + // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); BaseObjectIsPointer = false; @@ -874,6 +875,19 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { return false; } +/// \brief Build a MemberExpr or CXXQualifiedMemberExpr, as appropriate. +static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, + const CXXScopeSpec *SS, NamedDecl *Member, + SourceLocation Loc, QualType Ty) { + if (SS && SS->isSet()) + return new (C) CXXQualifiedMemberExpr(Base, isArrow, + (NestedNameSpecifier *)SS->getScopeRep(), + SS->getRange(), + Member, Loc, Ty); + + return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); +} + /// \brief Complete semantic analysis for a reference to the given declaration. Sema::OwningExprResult Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, @@ -985,8 +999,8 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, return ExprError(); if (DiagnoseUseOfDecl(D, Loc)) return ExprError(); - return Owned(new (Context) MemberExpr(This, true, D, - Loc, MemberType)); + return Owned(BuildMemberExpr(Context, This, true, SS, D, + Loc, MemberType)); } } } @@ -1953,7 +1967,7 @@ ObjCMethodDecl *Sema::FindMethodInNestedImplementations( return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel); return Method; } - + Action::OwningExprResult Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, @@ -2112,37 +2126,37 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, MarkDeclarationReferenced(MemberLoc, FD); if (PerformObjectMemberConversion(BaseExpr, FD)) return ExprError(); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD, - MemberLoc, MemberType)); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + FD, MemberLoc, MemberType)); } if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - Var, MemberLoc, - Var->getType().getNonReferenceType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Var, MemberLoc, + Var->getType().getNonReferenceType())); } if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - MemberFn, MemberLoc, - MemberFn->getType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + MemberFn, MemberLoc, + MemberFn->getType())); } if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - FunTmpl, MemberLoc, - Context.OverloadTy)); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + FunTmpl, MemberLoc, + Context.OverloadTy)); } if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl, - MemberLoc, Context.OverloadTy)); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Ovl, MemberLoc, Context.OverloadTy)); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - Enum, MemberLoc, Enum->getType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Enum, MemberLoc, Enum->getType())); } if (isa<TypeDecl>(MemberDecl)) return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type) @@ -4802,6 +4816,7 @@ static NamedDecl *getPrimaryDecl(Expr *E) { case Stmt::QualifiedDeclRefExprClass: return cast<DeclRefExpr>(E)->getDecl(); case Stmt::MemberExprClass: + case Stmt::CXXQualifiedMemberExprClass: // If this is an arrow operator, the address is an offset from // the base's value, so the object the base refers to is // irrelevant. diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 77d5220abd8..8aabad575a2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1421,6 +1421,28 @@ public: RParenLoc); } + /// \brief Build a new qualified member access expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + OwningExprResult RebuildCXXQualifiedMemberExpr(ExprArg Base, + SourceLocation OpLoc, + bool isArrow, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + SourceLocation MemberLoc, + NamedDecl *Member) { + CXXScopeSpec SS; + SS.setRange(QualifierRange); + SS.setScopeRep(Qualifier); + return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, + isArrow? tok::arrow : tok::period, + MemberLoc, + /*FIXME*/*Member->getIdentifier(), + /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0), + &SS); + } + /// \brief Build a new member reference expression. /// /// By default, performs semantic analysis to build the new expression. @@ -3992,6 +4014,44 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( E->getRParenLoc()); } +template<typename Derived> +Sema::OwningExprResult +TreeTransform<Derived>::TransformCXXQualifiedMemberExpr( + CXXQualifiedMemberExpr *E) { + OwningExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return SemaRef.ExprError(); + + NamedDecl *Member + = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getMemberDecl())); + if (!Member) + return SemaRef.ExprError(); + + NestedNameSpecifier *Qualifier + = getDerived().TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (Qualifier == 0) + return SemaRef.ExprError(); + + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase() && + Member == E->getMemberDecl() && + Qualifier == E->getQualifier()) + return SemaRef.Owned(E->Retain()); + + // FIXME: Bogus source location for the operator + SourceLocation FakeOperatorLoc + = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd()); + + return getDerived().RebuildCXXQualifiedMemberExpr(move(Base), + FakeOperatorLoc, + E->isArrow(), + Qualifier, + E->getQualifierRange(), + E->getMemberLoc(), + Member); +} + template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( |