From: Douglas Gregor Date: Mon, 28 Feb 2011 18:50:33 +0000 (+0000) Subject: Push nested-name-specifier source location information into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c3179cf463c3b3b8c21dbb955f933ba50b74f28;p=clang Push nested-name-specifier source location information into CXXDependentScopeMemberExpr, and clean up instantiation of nested-name-specifiers with dependent template specialization types in the process. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126663 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 225db3c11f..2e6421d608 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -2186,10 +2186,7 @@ class CXXDependentScopeMemberExpr : public Expr { SourceLocation OperatorLoc; /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifier *Qualifier; - - /// \brief The source range covering the nested name specifier. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief In a qualified member access expression such as t->Base::f, this /// member stores the resolves of name lookup in the context of the member @@ -2208,19 +2205,19 @@ class CXXDependentScopeMemberExpr : public Expr { CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); + friend class ASTStmtReader; + public: CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo); @@ -2228,8 +2225,7 @@ public: Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2249,30 +2245,27 @@ public: assert(!isImplicitAccess()); return cast(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - - /// \brief Retrieve the source range covering the nested-name-specifier - /// that qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. @@ -2287,26 +2280,20 @@ public: NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } - void setFirstQualifierFoundInScope(NamedDecl *D) { - FirstQualifierFoundInScope = D; - } /// \brief Retrieve the name of the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; } /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } - void setMember(DeclarationName N) { MemberNameInfo.setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } - void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); } /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f. @@ -2376,7 +2363,7 @@ public: if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + Range.setBegin(getQualifierLoc().getBeginLoc()); else Range.setBegin(MemberNameInfo.getBeginLoc()); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e85b6dcd27..3a07690f11 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1684,7 +1684,7 @@ DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b5fd70048f..7768630749 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2183,6 +2183,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, SourceLocation NameLoc, const TemplateArgumentListInfo &Args, QualType CanonType) const { + assert(!Name.getAsDependentTemplateName() && + "No dependent template names here!"); QualType TST = getTemplateSpecializationType(Name, Args, CanonType); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); @@ -2200,6 +2202,9 @@ QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, QualType Canon) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + unsigned NumArgs = Args.size(); llvm::SmallVector ArgVec; @@ -2216,6 +2221,9 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, QualType Canon) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + if (!Canon.isNull()) Canon = getCanonicalType(Canon); else @@ -2240,6 +2248,9 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); llvm::SmallVector CanonArgs; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 4f4a6b4944..b1e60102ed 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -689,20 +689,20 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, OK_Ordinary, true, true, ((Base && Base->containsUnexpandedParameterPack()) || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(TemplateArgs != 0), - OperatorLoc(OperatorLoc), - Qualifier(Qualifier), QualifierRange(QualifierRange), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { if (TemplateArgs) { @@ -719,18 +719,19 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, OK_Ordinary, true, true, ((Base && Base->containsUnexpandedParameterPack()) || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier()-> + containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), - Qualifier(Qualifier), QualifierRange(QualifierRange), + QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { } @@ -738,15 +739,14 @@ CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { if (!TemplateArgs) return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, - Qualifier, QualifierRange, + QualifierLoc, FirstQualifierFoundInScope, MemberNameInfo); @@ -757,7 +757,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, void *Mem = C.Allocate(size, llvm::alignOf()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, - Qualifier, QualifierRange, + QualifierLoc, FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs); } @@ -768,8 +768,8 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { if (!HasExplicitTemplateArgs) return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), 0, - SourceRange(), 0, + 0, SourceLocation(), + NestedNameSpecifierLoc(), 0, DeclarationNameInfo()); std::size_t size = sizeof(CXXDependentScopeMemberExpr) + @@ -777,8 +777,8 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, void *Mem = C.Allocate(size, llvm::alignOf()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), 0, - SourceRange(), 0, + 0, SourceLocation(), + NestedNameSpecifierLoc(), 0, DeclarationNameInfo(), 0); E->HasExplicitTemplateArgs = true; return E; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 415ab3f38d..2abbcf0acd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1350,10 +1350,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo TList; if (ULE->hasExplicitTemplateArgs()) ULE->copyTemplateArgumentsInto(TList); + + // FIXME: We should have nested-name-specifier location info in + // the ULE itself. + CXXScopeSpec SS; + SS.MakeTrivial(Context, ULE->getQualifier(), + ULE->getQualifierRange()); + CXXDependentScopeMemberExpr *DepExpr = CXXDependentScopeMemberExpr::Create( Context, DepThis, DepThisType, true, SourceLocation(), - ULE->getQualifier(), ULE->getQualifierRange(), NULL, + SS.getWithLocInContext(Context), NULL, R.getLookupNameInfo(), &TList); CallsUndergoingInstantiation.back()->setCallee(DepExpr); } else { @@ -3269,8 +3276,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // must have pointer type, and the accessed type is the pointee. return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, - SS.getScopeRep(), - SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index cbfd7b0939..01850353fd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -368,9 +368,6 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - NestedNameSpecifier *Qualifier - = static_cast(SS.getScopeRep()); - DeclContext *DC = getFunctionLevelDeclContext(); if (!isAddressOfOperand && @@ -386,7 +383,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, /*This*/ 0, ThisType, /*IsArrow*/ true, /*Op*/ SourceLocation(), - Qualifier, SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 8f875fbef0..4e2902690c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1975,16 +1975,15 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE, - QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -2601,10 +2600,11 @@ TreeTransform::TransformNestedNameSpecifierLoc( << TL.getType() << SS.getRange(); return NestedNameSpecifierLoc(); } - } + } - // The qualifier-in-scope only applies to the leftmost entity. + // The qualifier-in-scope and object type only apply to the leftmost entity. FirstQualifierInScope = 0; + ObjectType = QualType(); } // Don't rebuild the nested-name-specifier if we don't have to. @@ -3273,17 +3273,6 @@ TreeTransform::TransformTypeInObjectScope(TypeLoc TL, CXXScopeSpec &SS) { // FIXME: Painfully copy-paste from the above! - // TODO: in some cases, we might have some verification to do here. - if (ObjectType.isNull()) { - TypeLocBuilder TLB; - TLB.reserve(TL.getFullDataSize()); - QualType Result = getDerived().TransformType(TLB, TL); - if (Result.isNull()) - return TypeLoc(); - - return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); - } - QualType T = TL.getType(); if (getDerived().AlreadyTransformed(T)) return TL; @@ -3308,12 +3297,9 @@ TreeTransform::TransformTypeInObjectScope(TypeLoc TL, = cast(TL); TemplateName Template - = SemaRef.Context.getDependentTemplateName( - SpecTL.getTypePtr()->getQualifier(), - SpecTL.getTypePtr()->getIdentifier()); - - Template = getDerived().TransformTemplateName(Template, ObjectType, - UnqualLookup); + = getDerived().RebuildTemplateName(SS.getScopeRep(), SS.getRange(), + *SpecTL.getTypePtr()->getIdentifier(), + ObjectType, UnqualLookup); if (Template.isNull()) return TypeLoc(); @@ -7079,16 +7065,16 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( // the member name. NamedDecl *FirstQualifierInScope = getDerived().TransformFirstQualifierInScope( - E->getFirstQualifierFoundInScope(), - E->getQualifierRange().getBegin()); + E->getFirstQualifierFoundInScope(), + E->getQualifierLoc().getBeginLoc()); - NestedNameSpecifier *Qualifier = 0; + NestedNameSpecifierLoc QualifierLoc; if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - ObjectType, - FirstQualifierInScope); - if (!Qualifier) + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(), + ObjectType, + FirstQualifierInScope); + if (!QualifierLoc) return ExprError(); } @@ -7107,7 +7093,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( if (!getDerived().AlwaysRebuild() && Base.get() == OldBase && BaseType == E->getBaseType() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && NameInfo.getName() == E->getMember() && FirstQualifierInScope == E->getFirstQualifierFoundInScope()) return SemaRef.Owned(E); @@ -7116,8 +7102,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, /*TemplateArgs*/ 0); @@ -7133,8 +7118,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, &TransArgs); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 42f0b1aace..24ff7e8bd9 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1201,14 +1201,13 @@ ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), Record[Idx++]); - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(ReadSourceRange(Record, Idx)); - E->setFirstQualifierFoundInScope( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->Base = Reader.ReadSubExpr(); + E->BaseType = Reader.GetType(Record[Idx++]); + E->IsArrow = Record[Idx++]; + E->OperatorLoc = ReadSourceLocation(Record, Idx); + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + E->FirstQualifierFoundInScope + = cast_or_null(Reader.GetDecl(Record[Idx++])); ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index af846a9280..6e81ebbd1b 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1196,8 +1196,7 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ Writer.AddTypeRef(E->getBaseType(), Record); Record.push_back(E->isArrow()); Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); Writer.AddDeclarationNameInfo(E->MemberNameInfo, Record); Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; diff --git a/test/SemaCXX/nested-name-spec-locations.cpp b/test/SemaCXX/nested-name-spec-locations.cpp index 25914df627..344826df5c 100644 --- a/test/SemaCXX/nested-name-spec-locations.cpp +++ b/test/SemaCXX/nested-name-spec-locations.cpp @@ -65,6 +65,12 @@ void PseudoDestructorExprCheck( template struct DependentScopedDeclRefExpr { void f() { - outer_alias::inner::X0::value = 17; + outer_alias::inner::X0::type + * // expected-error{{as a pointer to a reference of type}} + >::value = 17; } }; + +void DependentScopedDeclRefExprCheck(DependentScopedDeclRefExpr t) { + t.f(); // expected-note{{in instantiation of member function}} +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index cd1b8d6667..5df33eb573 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1797,8 +1797,8 @@ void EnqueueVisitor:: VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs()); AddDeclarationNameInfo(E); - if (NestedNameSpecifier *Qualifier = E->getQualifier()) - AddNestedNameSpecifier(Qualifier, E->getQualifierRange()); + if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc()) + AddNestedNameSpecifierLoc(QualifierLoc); if (!E->isImplicitAccess()) AddStmt(E->getBase()); }