diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 58 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 44 |
7 files changed, 131 insertions, 24 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 60d8e5f987b..e756b41b12f 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -182,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()), - GlobalNewDeleteDeclared(false), + GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), CurrentInstantiationScope(0) { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 23bab230097..230bcffa722 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -18,7 +18,9 @@ #include "IdentifierResolver.h" #include "CXXFieldCollector.h" #include "SemaOverload.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/Action.h" @@ -245,6 +247,12 @@ public: /// have been declared. bool GlobalNewDeleteDeclared; + /// A flag that indicates when we are processing an unevaluated operand + /// (C++0x [expr]). C99 has the same notion of declarations being + /// "used" and C++03 has the notion of "potentially evaluated", but we + /// adopt the C++0x terminology since it is most precise. + bool InUnevaluatedOperand; + /// \brief Whether the code handled by Sema should be considered a /// complete translation unit or not. /// @@ -454,6 +462,19 @@ public: virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body); DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body, bool IsInstantiation); + + /// \brief Diagnose any unused parameters in the given sequence of + /// ParmVarDecl pointers. + template<typename InputIterator> + void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) { + for (; Param != ParamEnd; ++Param) { + if (!(*Param)->isUsed() && (*Param)->getDeclName() && + !(*Param)->template hasAttr<UnusedAttr>(Context)) + Diag((*Param)->getLocation(), diag::warn_unused_parameter) + << (*Param)->getDeclName(); + } + } + void DiagnoseInvalidJumps(Stmt *Body); virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); @@ -694,6 +715,7 @@ public: bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, const OverloadCandidate& Cand2); OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, + SourceLocation Loc, OverloadCandidateSet::iterator& Best); void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool OnlyViable); @@ -1312,6 +1334,14 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs); + virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) { + bool Result = InUnevaluatedOperand; + InUnevaluatedOperand = UnevaluatedOperand; + return Result; + } + + void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); + // Primary Expressions. virtual SourceRange getExprRange(ExprTy *E) const; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c4d1fe9983a..2dd02af7b91 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3094,10 +3094,23 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, Stmt *Body = BodyArg.takeAs<Stmt>(); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) { FD->setBody(Body); + + if (!FD->isInvalidDecl()) + DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) + if (Method->isVirtual() && !Method->isPure()) + MarkDeclarationReferenced(Method->getLocation(), Method); + assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); + + if (!MD->isInvalidDecl()) + DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); } else { Body->Destroy(Context); return DeclPtrTy(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fd1cc0406fc..8c547cd1ccf 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2031,7 +2031,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, // constructors, we'll need to make them appear here. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Loc, Best)) { case OR_Success: // We found a constructor. Return it. return cast<CXXConstructorDecl>(Best->Function); @@ -2263,7 +2263,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) { case OR_Success: // This is a direct binding. BindsDirectly = true; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index de568193119..692502bbbe8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -627,6 +627,7 @@ DeclRefExpr * Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, bool TypeDependent, bool ValueDependent, const CXXScopeSpec *SS) { + MarkDeclarationReferenced(Loc, D); if (SS && !SS->isEmpty()) { return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent, SS->getRange(), @@ -721,6 +722,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). if (BaseObjectExpr) BaseObjectExpr->Destroy(Context); + MarkDeclarationReferenced(Loc, BaseObject); BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(), SourceLocation()); ExtraQuals @@ -777,6 +779,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, = MemberType.getCVRQualifiers() | ExtraQuals; MemberType = MemberType.getQualifiedType(combinedQualifiers); } + MarkDeclarationReferenced(Loc, *FI); Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); BaseObjectIsPointer = false; @@ -876,6 +879,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // turn this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false); + MarkDeclarationReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, SelfExpr.takeAs<Expr>(), true, true)); @@ -1025,6 +1029,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Build the implicit member access expression. Expr *This = new (Context) CXXThisExpr(SourceLocation(), MD->getThisType(Context)); + MarkDeclarationReferenced(Loc, D); return Owned(new (Context) MemberExpr(This, true, D, Loc, MemberType)); } @@ -1125,6 +1130,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // as they do not get snapshotted. // if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) { + MarkDeclarationReferenced(Loc, VD); QualType ExprTy = VD->getType().getNonReferenceType(); // The BlocksAttr indicates the variable is bound by-reference. if (VD->getAttr<BlocksAttr>(Context)) @@ -1579,7 +1585,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -1689,7 +1695,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, LLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -5258,7 +5264,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BSI->isVariadic, 0); // FIXME: Check that return/parameter types are complete/non-abstract - + DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end()); BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. @@ -5425,3 +5431,49 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ *Result = EvalResult.Val.getInt(); return false; } + + +/// \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?"); + + // Mark a parameter declaration "used", regardless of whether we're in a + // template or not. + if (isa<ParmVarDecl>(D)) + D->setUsed(true); + + // Do not mark anything as "used" within a dependent context; wait for + // an instantiation. + if (CurContext->isDependentContext()) + return; + + // If we are in an unevaluated operand, don't mark any definitions as used. + if (InUnevaluatedOperand) + return; + + // Note that this declaration has been used. + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + // FIXME: implicit template instantiation + // FIXME: keep track of references to static functions + (void)Function; + Function->setUsed(true); + return; + } + + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + (void)Var; + // FIXME: implicit template instantiation + // FIXME: keep track of references to static data? + D->setUsed(true); + } +} + diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7353efbae7d..bec595ca9cf 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -546,7 +546,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Do the resolution. OverloadCandidateSet::iterator Best; - switch(BestViableFunction(Candidates, Best)) { + switch(BestViableFunction(Candidates, StartLoc, Best)) { case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; @@ -1175,7 +1175,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; - switch (Self.BestViableFunction(CandidateSet, Best)) { + switch (Self.BestViableFunction(CandidateSet, Loc, Best)) { case Sema::OR_Success: // We found a match. Perform the conversions on the arguments and move on. if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e81985b74a9..11cd5107fc6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1379,7 +1379,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) { case OR_Success: // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor @@ -3445,14 +3445,21 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, return false; } -/// BestViableFunction - Computes the best viable function (C++ 13.3.3) -/// within an overload candidate set. If overloading is successful, -/// the result will be OR_Success and Best will be set to point to the -/// best viable function within the candidate set. Otherwise, one of -/// several kinds of errors will be returned; see -/// Sema::OverloadingResult. +/// \brief Computes the best viable function (C++ 13.3.3) +/// within an overload candidate set. +/// +/// \param CandidateSet the set of candidate functions. +/// +/// \param Loc the location of the function name (or operator symbol) for +/// which overload resolution occurs. +/// +/// \param Best f overload resolution was successful or found a deleted +/// function, Best points to the candidate function found. +/// +/// \returns The result of overload resolution. Sema::OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, + SourceLocation Loc, OverloadCandidateSet::iterator& Best) { // Find the best viable function. @@ -3487,9 +3494,14 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, Best->Function->getAttr<UnavailableAttr>(Context))) return OR_Deleted; - // If Best refers to a function that is either deleted (C++0x) or - // unavailable (Clang extension) report an error. - + // C++ [basic.def.odr]p2: + // An overloaded function is used if it is selected by overload resolution + // when referred to from a potentially-evaluated expression. [Note: this + // covers calls to named functions (5.2.2), operator overloading + // (clause 13), user-defined conversions (12.3.2), allocation function for + // placement new (5.3.4), as well as non-default initialization (8.5). + if (Best->Function) + MarkDeclarationReferenced(Loc, Best->Function); return OR_Success; } @@ -3709,7 +3721,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, CandidateSet); OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { case OR_Success: return Best->Function; @@ -3815,7 +3827,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -3968,7 +3980,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -4094,7 +4106,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); break; @@ -4219,7 +4231,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call // below. @@ -4388,7 +4400,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: // Overload resolution succeeded; we'll build the call below. break; |