diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 14 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 322 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 25 |
10 files changed, 267 insertions, 213 deletions
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<DeclRefExpr>(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<DeclRefExpr>(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<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); } llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; @@ -3304,7 +3304,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Base->getType() << Base->getSourceRange()); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); } // Virtual bases. @@ -3332,7 +3332,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, PDiag(diag::err_access_dtor_vbase) << VBase->getType()); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(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<Expr>(); 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<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(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<BlocksAttr>(); @@ -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<FieldDecl>(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<VarDecl>(D) && !isa<FunctionDecl>(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<CXXConstructorDecl>(D)) { + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(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<CXXDestructorDecl>(D)) { + } else if (CXXDestructorDecl *Destructor = + dyn_cast<CXXDestructorDecl>(Func)) { if (Destructor->isDefaulted() && !Destructor->isUsed(false)) DefineImplicitDestructor(Loc, Destructor); if (Destructor->isVirtual()) MarkVTableUsed(Loc, Destructor->getParent()); - } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { + } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(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<FunctionDecl>(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<CXXRecordDecl>(Function->getDeclContext()) && - cast<CXXRecordDecl>(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<CXXRecordDecl>(Func->getDeclContext()) && + cast<CXXRecordDecl>(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<VarDecl>(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<VarDecl>(D)) + MarkVariableReferenced(Loc, VD); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(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<CXXDestructorDecl*>(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<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(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<CXXDestructorDecl*>(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<DeclRefExpr>(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<VarDecl>(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<FunctionDecl>(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, Memb |