From: Eli Friedman Date: Thu, 2 Feb 2012 03:46:19 +0000 (+0000) Subject: Split Sema::MarkDeclarationReferenced into multiple functions; the additional entry... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5f2987c11491edb186401d4e8eced275f0ea7c5e;p=clang Split Sema::MarkDeclarationReferenced into multiple functions; the additional entry points are needed to implement C++11 odr-use marking correctly. No functional change in this patch; I'll actually make the change which fixes the odr-use marking in a followup patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149586 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ff6b1ae8af..88a4d0f8e2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2265,7 +2265,19 @@ public: ExprResult TranformToPotentiallyEvaluated(Expr *E); ExprResult HandleExprEvaluationContextForTypeof(Expr *E); - void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); + // Functions for marking a declaration referenced. These functions also + // contain the relevant logic for marking if a reference to a function or + // variable is an odr-use (in the C++11 sense). There are separate variants + // for expressions referring to a decl; these exist because odr-use marking + // needs to be delayed for some constant variables when we build one of the + // named expressions. + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D); + void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func); + void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); + void MarkBlockDeclRefReferenced(BlockDeclRefExpr *E); + void MarkDeclRefReferenced(DeclRefExpr *E); + void MarkMemberReferenced(MemberExpr *E); + void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); void MarkDeclarationsReferencedInExpr(Expr *E); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index d4b9988d88..d1dc0de5cb 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2160,7 +2160,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { } D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD)); - S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD); + S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); } /// Handle __attribute__((format_arg((idx)))) attribute based on diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d83bf08891..d52ee12837 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2382,14 +2382,14 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); - SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param); - Expr *CopyCtorArg = DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param, Constructor->getLocation(), ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast(CopyCtorArg)); + // Cast to the base class to avoid ambiguities. QualType ArgTy = SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), @@ -2454,8 +2454,6 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); - SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param); - // Suppress copying zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) return false; @@ -2465,6 +2463,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, SourceLocation(), Param, Loc, ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast(MemberExprBase)); + if (Moving) { MemberExprBase = CastForMoving(SemaRef, MemberExprBase); } @@ -2796,7 +2796,7 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, Constructor->setCtorInitializers(initializer); if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { - MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor); + MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); } @@ -3272,7 +3272,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Field->getDeclName() << FieldType); - MarkDeclarationReferenced(Location, const_cast(Dtor)); + MarkFunctionReferenced(Location, const_cast(Dtor)); } llvm::SmallPtrSet DirectVirtualBases; @@ -3304,7 +3304,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Base->getType() << Base->getSourceRange()); - MarkDeclarationReferenced(Location, const_cast(Dtor)); + MarkFunctionReferenced(Location, const_cast(Dtor)); } // Virtual bases. @@ -3332,7 +3332,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, PDiag(diag::err_access_dtor_vbase) << VBase->getType()); - MarkDeclarationReferenced(Location, const_cast(Dtor)); + MarkFunctionReferenced(Location, const_cast(Dtor)); } } @@ -5306,7 +5306,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; - MarkDeclarationReferenced(Loc, OperatorDelete); + MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete); } @@ -9030,7 +9030,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); } - MarkDeclarationReferenced(ConstructLoc, Constructor); + MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, HadMultipleCandidates, RequiresZeroInit, @@ -9052,7 +9052,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, Expr *Temp = TempResult.takeAs(); CheckImplicitConversions(Temp, VD->getLocation()); - MarkDeclarationReferenced(VD->getLocation(), Constructor); + MarkFunctionReferenced(VD->getLocation(), Constructor); Temp = MaybeCreateExprWithCleanups(Temp); VD->setInit(Temp); @@ -9068,7 +9068,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (ClassDecl->isDependentContext()) return; CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkDeclarationReferenced(VD->getLocation(), Destructor); + MarkFunctionReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, PDiag(diag::err_access_dtor_var) << VD->getDeclName() @@ -10905,7 +10905,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] if (MD->isVirtual() && !MD->isPure()) - MarkDeclarationReferenced(Loc, MD); + MarkFunctionReferenced(Loc, MD); } // Only classes that have virtual bases need a VTT. @@ -10965,7 +10965,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { ->getAs()) { CXXRecordDecl *RD = cast(RecordTy->getDecl()); if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { - MarkDeclarationReferenced(Field->getLocation(), Destructor); + MarkFunctionReferenced(Field->getLocation(), Destructor); CheckDestructorAccess(Field->getLocation(), Destructor, PDiag(diag::err_access_dtor_ivar) << Context.getBaseElementType(Field->getType())); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5de0388c06..3862286f9c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1331,8 +1331,6 @@ static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc, return CR_Error; } - S.MarkDeclarationReferenced(loc, var); - // The BlocksAttr indicates the variable is bound by-reference. bool byRef = var->hasAttr(); @@ -1411,6 +1409,8 @@ static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *VD, NameInfo.getLoc(), true); } + S.MarkBlockDeclRefReferenced(BDRE); + return S.Owned(BDRE); } @@ -1442,13 +1442,13 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, } } - MarkDeclarationReferenced(NameInfo.getLoc(), D); + DeclRefExpr *E = DeclRefExpr::Create(Context, + SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + SourceLocation(), + D, NameInfo, Ty, VK); - Expr *E = DeclRefExpr::Create(Context, - SS ? SS->getWithLocInContext(Context) - : NestedNameSpecifierLoc(), - SourceLocation(), - D, NameInfo, Ty, VK); + MarkDeclRefReferenced(E); // Just in case we're building an illegal pointer-to-member. FieldDecl *FD = dyn_cast(D); @@ -2004,7 +2004,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); - MarkDeclarationReferenced(Loc, IV); + MarkAnyDeclReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, SelfExpr.take(), true, true)); @@ -3742,7 +3742,7 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, DeclRefExpr *ConfigDR = new (Context) DeclRefExpr( ConfigDecl, ConfigQTy, VK_LValue, LLLLoc); - MarkDeclarationReferenced(LLLLoc, ConfigDecl); + MarkFunctionReferenced(LLLLoc, ConfigDecl); return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0, /*IsExecConfig=*/true); @@ -9436,9 +9436,7 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { } void Sema::PopExpressionEvaluationContext() { - // Pop the current expression evaluation context off the stack. - ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back(); - ExprEvalContexts.pop_back(); + ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); // When are coming out of an unevaluated context, clear out any // temporaries that we may have created as part of the evaluation of @@ -9453,6 +9451,9 @@ void Sema::PopExpressionEvaluationContext() { } else { ExprNeedsCleanups |= Rec.ParentNeedsCleanups; } + + // Pop the current expression evaluation context off the stack. + ExprEvalContexts.pop_back(); } void Sema::DiscardCleanupsInEvaluationContext() { @@ -9468,55 +9469,49 @@ ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { return TranformToPotentiallyEvaluated(E); } -/// \brief Note that the given declaration was referenced in the source code. -/// -/// This routine should be invoke whenever a given declaration is referenced -/// in the source code, and where that reference occurred. If this declaration -/// reference means that the the declaration is used (C++ [basic.def.odr]p2, -/// C99 6.9p3), then the declaration will be marked as used. -/// -/// \param Loc the location where the declaration was referenced. -/// -/// \param D the declaration that has been referenced by the source code. -void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { - assert(D && "No declaration?"); - - D->setReferenced(); - - if (D->isUsed(false)) - return; - - if (!isa(D) && !isa(D)) - return; - +bool IsPotentiallyEvaluatedContext(Sema &SemaRef) { // Do not mark anything as "used" within a dependent context; wait for // an instantiation. - if (CurContext->isDependentContext()) - return; + if (SemaRef.CurContext->isDependentContext()) + return false; - switch (ExprEvalContexts.back().Context) { - case Unevaluated: + switch (SemaRef.ExprEvalContexts.back().Context) { + case Sema::Unevaluated: // We are in an expression that is not potentially evaluated; do nothing. // (Depending on how you read the standard, we actually do need to do // something here for null pointer constants, but the standard's // definition of a null pointer constant is completely crazy.) - return; + return false; - case ConstantEvaluated: - case PotentiallyEvaluated: + case Sema::ConstantEvaluated: + case Sema::PotentiallyEvaluated: // We are in a potentially evaluated expression (or a constant-expression // in C++03); we need to do implicit template instantiation, implicitly // define class members, and mark most declarations as used. - break; + return true; - case PotentiallyEvaluatedIfUsed: + case Sema::PotentiallyEvaluatedIfUsed: // Referenced declarations will only be used if the construct in the // containing expression is used. - return; + return false; } +} + +/// \brief Mark a function referenced, and check whether it is odr-used +/// (C++ [basic.def.odr]p2, C99 6.9p3) +void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { + assert(Func && "No function?"); + + Func->setReferenced(); + + if (Func->isUsed(false)) + return; + + if (!IsPotentiallyEvaluatedContext(*this)) + return; // Note that this declaration has been used. - if (CXXConstructorDecl *Constructor = dyn_cast(D)) { + if (CXXConstructorDecl *Constructor = dyn_cast(Func)) { if (Constructor->isDefaulted()) { if (Constructor->isDefaultConstructor()) { if (Constructor->isTrivial()) @@ -9533,12 +9528,13 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } MarkVTableUsed(Loc, Constructor->getParent()); - } else if (CXXDestructorDecl *Destructor = dyn_cast(D)) { + } else if (CXXDestructorDecl *Destructor = + dyn_cast(Func)) { if (Destructor->isDefaulted() && !Destructor->isUsed(false)) DefineImplicitDestructor(Loc, Destructor); if (Destructor->isVirtual()) MarkVTableUsed(Loc, Destructor->getParent()); - } else if (CXXMethodDecl *MethodDecl = dyn_cast(D)) { + } else if (CXXMethodDecl *MethodDecl = dyn_cast(Func)) { if (MethodDecl->isDefaulted() && MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { if (!MethodDecl->isUsed(false)) { @@ -9550,99 +9546,143 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } else if (MethodDecl->isVirtual()) MarkVTableUsed(Loc, MethodDecl->getParent()); } - if (FunctionDecl *Function = dyn_cast(D)) { - // Recursive functions should be marked when used from another function. - if (CurContext == Function) return; - - // Implicit instantiation of function templates and member functions of - // class templates. - if (Function->isImplicitlyInstantiable()) { - bool AlreadyInstantiated = false; - if (FunctionTemplateSpecializationInfo *SpecInfo - = Function->getTemplateSpecializationInfo()) { - if (SpecInfo->getPointOfInstantiation().isInvalid()) - SpecInfo->setPointOfInstantiation(Loc); - else if (SpecInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) - AlreadyInstantiated = true; - } else if (MemberSpecializationInfo *MSInfo - = Function->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) - MSInfo->setPointOfInstantiation(Loc); - else if (MSInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) - AlreadyInstantiated = true; - } - if (!AlreadyInstantiated) { - if (isa(Function->getDeclContext()) && - cast(Function->getDeclContext())->isLocalClass()) - PendingLocalImplicitInstantiations.push_back(std::make_pair(Function, - Loc)); - else if (Function->getTemplateInstantiationPattern()->isConstexpr()) - // Do not defer instantiations of constexpr functions, to avoid the - // expression evaluator needing to call back into Sema if it sees a - // call to such a function. - InstantiateFunctionDefinition(Loc, Function); - else - PendingInstantiations.push_back(std::make_pair(Function, Loc)); - } - } else { - // Walk redefinitions, as some of them may be instantiable. - for (FunctionDecl::redecl_iterator i(Function->redecls_begin()), - e(Function->redecls_end()); i != e; ++i) { - if (!i->isUsed(false) && i->isImplicitlyInstantiable()) - MarkDeclarationReferenced(Loc, *i); - } + // Recursive functions should be marked when used from another function. + // FIXME: Is this really right? + if (CurContext == Func) return; + + // Implicit instantiation of function templates and member functions of + // class templates. + if (Func->isImplicitlyInstantiable()) { + bool AlreadyInstantiated = false; + if (FunctionTemplateSpecializationInfo *SpecInfo + = Func->getTemplateSpecializationInfo()) { + if (SpecInfo->getPointOfInstantiation().isInvalid()) + SpecInfo->setPointOfInstantiation(Loc); + else if (SpecInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) + AlreadyInstantiated = true; + } else if (MemberSpecializationInfo *MSInfo + = Func->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->setPointOfInstantiation(Loc); + else if (MSInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) + AlreadyInstantiated = true; + } + + if (!AlreadyInstantiated) { + if (isa(Func->getDeclContext()) && + cast(Func->getDeclContext())->isLocalClass()) + PendingLocalImplicitInstantiations.push_back(std::make_pair(Func, + Loc)); + else if (Func->getTemplateInstantiationPattern()->isConstexpr()) + // Do not defer instantiations of constexpr functions, to avoid the + // expression evaluator needing to call back into Sema if it sees a + // call to such a function. + InstantiateFunctionDefinition(Loc, Func); + else + PendingInstantiations.push_back(std::make_pair(Func, Loc)); } - - // Keep track of used but undefined functions. - if (!Function->isPure() && !Function->hasBody() && - Function->getLinkage() != ExternalLinkage) { - SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; + } else { + // Walk redefinitions, as some of them may be instantiable. + for (FunctionDecl::redecl_iterator i(Func->redecls_begin()), + e(Func->redecls_end()); i != e; ++i) { + if (!i->isUsed(false) && i->isImplicitlyInstantiable()) + MarkFunctionReferenced(Loc, *i); } + } - Function->setUsed(true); - return; + // Keep track of used but undefined functions. + if (!Func->isPure() && !Func->hasBody() && + Func->getLinkage() != ExternalLinkage) { + SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; } - if (VarDecl *Var = dyn_cast(D)) { - // Implicit instantiation of static data members of class templates. - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember()) { - MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); - assert(MSInfo && "Missing member specialization information?"); - if (MSInfo->getPointOfInstantiation().isInvalid() && - MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { - MSInfo->setPointOfInstantiation(Loc); - // This is a modification of an existing AST node. Notify listeners. - if (ASTMutationListener *L = getASTMutationListener()) - L->StaticDataMemberInstantiated(Var); - if (Var->isUsableInConstantExpressions()) - // Do not defer instantiations of variables which could be used in a - // constant expression. - InstantiateStaticDataMemberDefinition(Loc, Var); - else - PendingInstantiations.push_back(std::make_pair(Var, Loc)); - } - } + Func->setUsed(true); +} - // Keep track of used but undefined variables. We make a hole in - // the warning for static const data members with in-line - // initializers. - // FIXME: The hole we make for static const data members is too wide! - // We need to implement the C++11 rules for odr-used. - if (Var->hasDefinition() == VarDecl::DeclarationOnly - && Var->getLinkage() != ExternalLinkage - && !(Var->isStaticDataMember() && Var->hasInit())) { - SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; - } +/// \brief Mark a variable referenced, and check whether it is odr-used +/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be +/// used directly for normal expressions referring to VarDecl. +void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { + Var->setReferenced(); + + if (Var->isUsed(false)) + return; - D->setUsed(true); + if (!IsPotentiallyEvaluatedContext(*this)) return; + + // Implicit instantiation of static data members of class templates. + if (Var->isStaticDataMember() && + Var->getInstantiatedFromStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + if (MSInfo->getPointOfInstantiation().isInvalid() && + MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { + MSInfo->setPointOfInstantiation(Loc); + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + if (Var->isUsableInConstantExpressions()) + // Do not defer instantiations of variables which could be used in a + // constant expression. + InstantiateStaticDataMemberDefinition(Loc, Var); + else + PendingInstantiations.push_back(std::make_pair(Var, Loc)); + } + } + + // Keep track of used but undefined variables. We make a hole in + // the warning for static const data members with in-line + // initializers. + // FIXME: The hole we make for static const data members is too wide! + // We need to implement the C++11 rules for odr-used. + if (Var->hasDefinition() == VarDecl::DeclarationOnly + && Var->getLinkage() != ExternalLinkage + && !(Var->isStaticDataMember() && Var->hasInit())) { + SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; } + + Var->setUsed(true); +} + +static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, + Decl *D, Expr *E) { + // TODO: Add special handling for variables + SemaRef.MarkAnyDeclReferenced(Loc, D); +} + +/// \brief Perform reference-marking and odr-use handling for a +/// BlockDeclRefExpr. +void Sema::MarkBlockDeclRefReferenced(BlockDeclRefExpr *E) { + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E); +} + +/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr. +void Sema::MarkDeclRefReferenced(DeclRefExpr *E) { + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E); +} + +/// \brief Perform reference-marking and odr-use handling for a MemberExpr. +void Sema::MarkMemberReferenced(MemberExpr *E) { + MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E); +} + +/// \brief Perform marking for a reference to an aribitrary declaration. It +/// marks the declaration referenced, and performs odr-use checking for functions +/// and variables. This method should not be used when building an normal +/// expression which refers to a variable. +void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) { + if (VarDecl *VD = dyn_cast(D)) + MarkVariableReferenced(Loc, VD); + else if (FunctionDecl *FD = dyn_cast(D)) + MarkFunctionReferenced(Loc, FD); + else + D->setReferenced(); } namespace { @@ -9666,7 +9706,7 @@ namespace { bool MarkReferencedDecls::TraverseTemplateArgument( const TemplateArgument &Arg) { if (Arg.getKind() == TemplateArgument::Declaration) { - S.MarkDeclarationReferenced(Loc, Arg.getAsDecl()); + S.MarkAnyDeclReferenced(Loc, Arg.getAsDecl()); } return Inherited::TraverseTemplateArgument(Arg); @@ -9699,37 +9739,37 @@ namespace { explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } void VisitDeclRefExpr(DeclRefExpr *E) { - S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); + S.MarkDeclRefReferenced(E); } void VisitMemberExpr(MemberExpr *E) { - S.MarkDeclarationReferenced(E->getMemberLoc(), E->getMemberDecl()); + S.MarkMemberReferenced(E); Inherited::VisitMemberExpr(E); } void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - S.MarkDeclarationReferenced(E->getLocStart(), + S.MarkFunctionReferenced(E->getLocStart(), const_cast(E->getTemporary()->getDestructor())); Visit(E->getSubExpr()); } void VisitCXXNewExpr(CXXNewExpr *E) { if (E->getConstructor()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); + S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); if (E->getOperatorNew()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorNew()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); if (E->getOperatorDelete()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); Inherited::VisitCXXNewExpr(E); } void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs()) { CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); - S.MarkDeclarationReferenced(E->getLocStart(), + S.MarkFunctionReferenced(E->getLocStart(), S.LookupDestructor(Record)); } @@ -9737,12 +9777,12 @@ namespace { } void VisitCXXConstructExpr(CXXConstructExpr *E) { - S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); + S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); Inherited::VisitCXXConstructExpr(E); } void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); + S.MarkBlockDeclRefReferenced(E); } void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7e97b2919b..2fe0974bda 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -645,7 +645,7 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, if (!Destructor) return Owned(E); - MarkDeclarationReferenced(E->getExprLoc(), Destructor); + MarkFunctionReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_exception) << Ty); return Owned(E); @@ -1188,16 +1188,16 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // Mark the new and delete operators as referenced. if (OperatorNew) - MarkDeclarationReferenced(StartLoc, OperatorNew); + MarkFunctionReferenced(StartLoc, OperatorNew); if (OperatorDelete) - MarkDeclarationReferenced(StartLoc, OperatorDelete); + MarkFunctionReferenced(StartLoc, OperatorDelete); // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, // access and ambiguity control are done for the destructor. if (ArraySize && Constructor) { if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) { - MarkDeclarationReferenced(StartLoc, dtor); + MarkFunctionReferenced(StartLoc, dtor); CheckDestructorAccess(StartLoc, dtor, PDiag(diag::err_access_dtor) << Context.getBaseElementType(AllocType)); @@ -1517,7 +1517,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; - MarkDeclarationReferenced(StartLoc, FnDecl); + MarkFunctionReferenced(StartLoc, FnDecl); // The first argument is size_t, and the first parameter must be size_t, // too. This is checked on declaration and can be assumed. (It can't be // asserted on, though, since invalid decls are left in there.) @@ -1956,7 +1956,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!PointeeRD->hasTrivialDestructor()) if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { - MarkDeclarationReferenced(StartLoc, + MarkFunctionReferenced(StartLoc, const_cast(Dtor)); DiagnoseUseOfDecl(Dtor, StartLoc); } @@ -2005,7 +2005,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(); } - MarkDeclarationReferenced(StartLoc, OperatorDelete); + MarkFunctionReferenced(StartLoc, OperatorDelete); // Check access and ambiguity of operator delete and destructor. if (PointeeRD) { @@ -2049,7 +2049,7 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, ConditionVar->getType().getNonReferenceType(), VK_LValue)); - MarkDeclarationReferenced(ConditionVar->getLocation(), ConditionVar); + MarkDeclRefReferenced(cast(Condition.get())); if (ConvertToBoolean) { Condition = CheckBooleanCondition(Condition.take(), StmtLoc); @@ -3609,7 +3609,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS break; RHS = move(RHSRes); if (Best->Function) - Self.MarkDeclarationReferenced(QuestionLoc, Best->Function); + Self.MarkFunctionReferenced(QuestionLoc, Best->Function); return false; } @@ -4210,7 +4210,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); if (Destructor) { - MarkDeclarationReferenced(E->getExprLoc(), Destructor); + MarkFunctionReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_temp) << E->getType()); @@ -4687,7 +4687,7 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkDeclarationReferenced(Exp.get()->getLocStart(), Method); + MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, Exp.get()->getLocEnd()); diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index fb1dbcef84..1545d6ef20 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -776,7 +776,8 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, } /// \brief Build a MemberExpr AST node. -static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, +static MemberExpr *BuildMemberExpr(Sema &SemaRef, + ASTContext &C, Expr *Base, bool isArrow, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, ValueDecl *Member, @@ -786,9 +787,12 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = 0) { assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); - return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), - TemplateKWLoc, Member, FoundDecl, MemberNameInfo, - TemplateArgs, Ty, VK, OK); + MemberExpr *E = + MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), + TemplateKWLoc, Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty, VK, OK); + SemaRef.MarkMemberReferenced(E); + return E; } ExprResult @@ -908,9 +912,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr, OpLoc); if (VarDecl *Var = dyn_cast(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, Var); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - Var, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary)); } @@ -926,17 +929,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, type = MemberFn->getType(); } - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - MemberFn, FoundDecl, MemberNameInfo, - type, valueKind, OK_Ordinary)); + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, MemberFn, FoundDecl, + MemberNameInfo, type, valueKind, + OK_Ordinary)); } assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - Enum, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary)); } @@ -1540,13 +1542,12 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, MemberType = S.Context.getQualifiedType(MemberType, Combined); } - S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); ExprResult Base = S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); - return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, + return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS, /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 3da73b77bb..096ca7c93b 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3156,7 +3156,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // This is the overload that will actually be used for the initialization, so // mark it as used. - S.MarkDeclarationReferenced(DeclLoc, Function); + S.MarkFunctionReferenced(DeclLoc, Function); // Compute the returned type of the conversion. if (isa(Function)) @@ -3679,7 +3679,7 @@ static void TryUserDefinedConversion(Sema &S, } FunctionDecl *Function = Best->Function; - S.MarkDeclarationReferenced(DeclLoc, Function); + S.MarkFunctionReferenced(DeclLoc, Function); bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa(Function)) { @@ -4388,7 +4388,7 @@ static ExprResult CopyObject(Sema &S, return S.Owned(CurInitExpr); } - S.MarkDeclarationReferenced(Loc, Constructor); + S.MarkFunctionReferenced(Loc, Constructor); // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or @@ -4531,7 +4531,7 @@ PerformConstructorInitialization(Sema &S, // An explicitly-constructed temporary, e.g., X(1, 2). unsigned NumExprs = ConstructorArgs.size(); Expr **Exprs = (Expr **)ConstructorArgs.take(); - S.MarkDeclarationReferenced(Loc, Constructor); + S.MarkFunctionReferenced(Loc, Constructor); S.DiagnoseUseOfDecl(Constructor, Loc); TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); @@ -4899,7 +4899,7 @@ InitializationSequence::Perform(Sema &S, = S.LookupDestructor(cast(Record->getDecl())); S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); - S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor); + S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f681a589cf..d09fd9dad2 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2893,7 +2893,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast(Best->Function)) { - S.MarkDeclarationReferenced(From->getLocStart(), Constructor); + S.MarkFunctionReferenced(From->getLocStart(), Constructor); // C++ [over.ics.user]p1: // If the user-defined conversion is specified by a @@ -2923,7 +2923,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } if (CXXConversionDecl *Conversion = dyn_cast(Best->Function)) { - S.MarkDeclarationReferenced(From->getLocStart(), Conversion); + S.MarkFunctionReferenced(From->getLocStart(), Conversion); // C++ [over.ics.user]p1: // @@ -3793,7 +3793,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, return false; if (Best->Function) - S.MarkDeclarationReferenced(DeclLoc, Best->Function); + S.MarkFunctionReferenced(DeclLoc, Best->Function); ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; @@ -8817,7 +8817,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn); + MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn); if (Complain) CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); } @@ -9380,7 +9380,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; - MarkDeclarationReferenced(Fn->getExprLoc(), FDecl); + MarkFunctionReferenced(Fn->getExprLoc(), FDecl); CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); @@ -9534,7 +9534,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(OpLoc, FnDecl); + MarkFunctionReferenced(OpLoc, FnDecl); // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { @@ -9755,7 +9755,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(OpLoc, FnDecl); + MarkFunctionReferenced(OpLoc, FnDecl); // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { @@ -9962,7 +9962,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(LLoc, FnDecl); + MarkFunctionReferenced(LLoc, FnDecl); CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LLoc); @@ -10211,7 +10211,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Best)) { case OR_Success: Method = cast(Best->Function); - MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method); + MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); @@ -10476,7 +10476,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, RParenLoc); } - MarkDeclarationReferenced(LParenLoc, Best->Function); + MarkFunctionReferenced(LParenLoc, Best->Function); CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); @@ -10666,7 +10666,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return ExprError(); } - MarkDeclarationReferenced(OpLoc, Best->Function); + MarkFunctionReferenced(OpLoc, Best->Function); CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 76663a2d12..322e473215 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3630,7 +3630,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Create the template argument. Converted = TemplateArgument(Entity->getCanonicalDecl()); - S.MarkDeclarationReferenced(Arg->getLocStart(), Entity); + S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity); return false; } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index d207eb632f..6bbb8316e5 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -5949,7 +5949,7 @@ TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + SemaRef.MarkDeclRefReferenced(E); return SemaRef.Owned(E); } @@ -6293,7 +6293,8 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member); + SemaRef.MarkMemberReferenced(E); + return SemaRef.Owned(E); } @@ -7117,11 +7118,11 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. if (Constructor) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); if (OperatorNew) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew); if (OperatorDelete) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); if (E->isArray() && Constructor && !E->getAllocatedType()->isDependentType()) { @@ -7130,7 +7131,7 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { if (const RecordType *RecordT = ElementType->getAs()) { CXXRecordDecl *Record = cast(RecordT->getDecl()); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Destructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor); } } } @@ -7202,15 +7203,15 @@ TreeTransform::TransformCXXDeleteExpr(CXXDeleteExpr *E) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. if (OperatorDelete) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); if (!E->getArgument()->isTypeDependent()) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs()) { CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); - SemaRef.MarkDeclarationReferenced(E->getLocStart(), - SemaRef.LookupDestructor(Record)); + SemaRef.MarkFunctionReferenced(E->getLocStart(), + SemaRef.LookupDestructor(Record)); } } @@ -7540,7 +7541,7 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { !ArgumentChanged) { // Mark the constructor as referenced. // FIXME: Instantiation-specific - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); return SemaRef.Owned(E); } @@ -7601,7 +7602,7 @@ TreeTransform::TransformCXXTemporaryObjectExpr( Constructor == E->getConstructor() && !ArgumentChanged) { // FIXME: Instantiation-specific - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); return SemaRef.MaybeBindToTemporary(E); } @@ -8253,7 +8254,7 @@ TreeTransform::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { ND == E->getDecl()) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + SemaRef.MarkBlockDeclRefReferenced(E); return SemaRef.Owned(E); }