[cfe-commits] r73797 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/Frontend/ lib/Parse/ lib/Sema/ test/Sema/ test/SemaObjC/

Douglas Gregor dgregor at apple.com
Fri Jun 19 16:52:43 PDT 2009


Author: dgregor
Date: Fri Jun 19 18:52:42 2009
New Revision: 73797

URL: http://llvm.org/viewvc/llvm-project?rev=73797&view=rev
Log:
Keep track of when declarations are "used" according to C and
C++. This logic is required to trigger implicit instantiation of
function templates and member functions of class templates, which will
be implemented separately.

This commit includes support for -Wunused-parameter, printing warnings
for named parameters that are not used within a function/Objective-C
method/block. Fixes <rdar://problem/6505209>.


Added:
    cfe/trunk/test/Sema/warn-unused-parameters.c
    cfe/trunk/test/SemaObjC/warn-unused-parameters.m
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Jun 19 18:52:42 2009
@@ -156,6 +156,10 @@
   /// the implementation rather than explicitly written by the user.
   bool Implicit : 1;
 
+  /// \brief Whether this declaration was "used", meaning that a definition is
+  /// required.
+  bool Used : 1;
+  
   /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
   unsigned IdentifierNamespace : 8;
   
@@ -174,7 +178,7 @@
   Decl(Kind DK, DeclContext *DC, SourceLocation L) 
     : NextDeclInContext(0), DeclCtx(DC), 
       Loc(L), DeclKind(DK), InvalidDecl(0),
-      HasAttrs(false), Implicit(false), 
+      HasAttrs(false), Implicit(false), Used(false),
       IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
     if (Decl::CollectingStats()) addDeclKind(DK);
   }
@@ -241,6 +245,11 @@
   bool isImplicit() const { return Implicit; }
   void setImplicit(bool I = true) { Implicit = I; }
   
+  /// \brief Whether this declaration was used, meaning that a definition
+  /// is required.
+  bool isUsed() const { return Used; }
+  void setUsed(bool U = true) { Used = U; }
+  
   unsigned getIdentifierNamespace() const {
     return IdentifierNamespace;
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Jun 19 18:52:42 2009
@@ -116,7 +116,9 @@
                         [FormatNonLiteral, FormatSecurity, FormatY2K]>;
 
 
-def Extra : DiagGroup<"extra">;
+def Extra : DiagGroup<"extra", [
+    UnusedParameter
+  ]>;
 
 def Most : DiagGroup<"most", [
     Comment,

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 19 18:52:42 2009
@@ -72,6 +72,8 @@
 def err_bad_variable_name : Error<
   "'%0' cannot be the name of a variable or data member">;
 def err_parameter_name_omitted : Error<"parameter name omitted">;
+def warn_unused_parameter : Warning<"unused parameter %0">,
+  InGroup<UnusedParameter>, DefaultIgnore;
 def warn_decl_in_param_list : Warning<
   "declaration of %0 will not be visible outside of this function">;
   

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Jun 19 18:52:42 2009
@@ -637,6 +637,18 @@
   // Expression Parsing Callbacks.
   //===--------------------------------------------------------------------===//
 
+  /// \brief Notifies the action when the parser is processing an unevaluated
+  /// operand.
+  ///
+  /// \param UnevaluatedOperand true to indicate that the parser is processing
+  /// an unevaluated operand, or false otherwise.
+  ///
+  /// \returns whether the the action module was previously in an unevaluated
+  /// operand.
+  virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) { 
+    return false;
+  }
+  
   // Primary Expressions.
 
   /// \brief Retrieve the source range that corresponds to the given

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Jun 19 18:52:42 2009
@@ -105,6 +105,24 @@
     }
   };
 
+  /// \brief RAII object that enters an unevaluated operand.
+  class EnterUnevaluatedOperand {    
+    /// \brief The action object.
+    Action &Actions;
+    
+    /// \brief Whether we were previously within an unevaluated operand.
+    bool PreviouslyInUnevaluatedOperand;
+    
+  public:
+    explicit EnterUnevaluatedOperand(Action &Actions) : Actions(Actions) { 
+      PreviouslyInUnevaluatedOperand = Actions.setUnevaluatedOperand(true);
+    }
+    
+    ~EnterUnevaluatedOperand() {
+      Actions.setUnevaluatedOperand(PreviouslyInUnevaluatedOperand);
+    }
+  };
+  
 public:
   Parser(Preprocessor &PP, Action &Actions);
   ~Parser();

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jun 19 18:52:42 2009
@@ -82,6 +82,7 @@
   if (Record[Idx++])
     D->addAttr(*Reader.getContext(), Reader.ReadAttributes());
   D->setImplicit(Record[Idx++]);
+  D->setUsed(Record[Idx++]);
   D->setAccess((AccessSpecifier)Record[Idx++]);
 }
 

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jun 19 18:52:42 2009
@@ -82,6 +82,7 @@
   Record.push_back(D->isInvalidDecl());
   Record.push_back(D->hasAttrs());
   Record.push_back(D->isImplicit());
+  Record.push_back(D->isUsed());
   Record.push_back(D->getAccess());
 }
 
@@ -360,6 +361,7 @@
   // know are true of all PARM_VAR_DECLs.
   if (!D->hasAttrs() &&
       !D->isImplicit() &&
+      !D->isUsed() &&
       D->getAccess() == AS_none &&
       D->getStorageClass() == 0 &&
       !D->hasCXXDirectInitializer() && // Can params have this ever?
@@ -434,6 +436,7 @@
   Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl (!?)
   Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs
   Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit
+  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
   
   // NamedDecl

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Jun 19 18:52:42 2009
@@ -2699,8 +2699,12 @@
     // things like '=' and '*='.  Sema rejects these in C89 mode because they
     // are not i-c-e's, so we don't need to distinguish between the two here.
     
-    // Parse the assignment-expression now.
-    NumElements = ParseAssignmentExpression();
+    // Parse the constant-expression or assignment-expression now (depending
+    // on dialect).
+    if (getLang().CPlusPlus)
+      NumElements = ParseConstantExpression();
+    else
+      NumElements = ParseAssignmentExpression();
   }
   
   // If there was an error parsing the assignment-expression, recover.

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Jun 19 18:52:42 2009
@@ -279,7 +279,7 @@
   }
   
   SourceLocation LParenLoc = ConsumeParen();
-  
+
   OwningExprResult AssertExpr(ParseConstantExpression());
   if (AssertExpr.isInvalid()) {
     SkipUntil(tok::semi);

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Jun 19 18:52:42 2009
@@ -276,6 +276,11 @@
 
 
 Parser::OwningExprResult Parser::ParseConstantExpression() {
+  // C++ [basic.def.odr]p2:
+  //   An expression is potentially evaluated unless it appears where an 
+  //   integral constant expression is required (see 5.19) [...].
+  EnterUnevaluatedOperand Unevaluated(Actions);
+  
   OwningExprResult LHS(ParseCastExpression(false));
   if (LHS.isInvalid()) return move(LHS);
 
@@ -971,8 +976,15 @@
       Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
       return ExprError();
     }
+    
+    // C++0x [expr.sizeof]p1:
+    //   [...] The operand is either an expression, which is an unevaluated 
+    //   operand (Clause 5) [...]
+    //
+    // The GNU typeof and alignof extensions also behave as unevaluated
+    // operands.
+    EnterUnevaluatedOperand Unevaluated(Actions);
     Operand = ParseCastExpression(true/*isUnaryExpression*/);
-
   } else {
     // If it starts with a '(', we know that it is either a parenthesized
     // type-name, or it is a unary-expression that starts with a compound
@@ -980,6 +992,14 @@
     // expression.
     ParenParseOption ExprType = CastExpr;
     SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+    
+    // C++0x [expr.sizeof]p1:
+    //   [...] The operand is either an expression, which is an unevaluated 
+    //   operand (Clause 5) [...]
+    //
+    // The GNU typeof and alignof extensions also behave as unevaluated
+    // operands.
+    EnterUnevaluatedOperand Unevaluated(Actions);
     Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
                                    CastTy, RParenLoc);
     CastRange = SourceRange(LParenLoc, RParenLoc);

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Jun 19 18:52:42 2009
@@ -377,6 +377,17 @@
     Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
                                     Ty.get(), RParenLoc);
   } else {
+    // C++0x [expr.typeid]p3:
+    //   When typeid is applied to an expression other than an lvalue of a 
+    //   polymorphic class type [...] The expression is an unevaluated 
+    //   operand (Clause 5).
+    //
+    // Note that we can't tell whether the expression is an lvalue of a 
+    // polymorphic class type until after we've parsed the expression, so
+    // we treat the expression as an unevaluated operand and let semantic
+    // analysis cope with case where the expression is not an unevaluated
+    // operand.
+    EnterUnevaluatedOperand Unevaluated(Actions);
     Result = ParseExpression();
 
     // Match the ')'.

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Jun 19 18:52:42 2009
@@ -182,7 +182,7 @@
     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) {
   

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jun 19 18:52:42 2009
@@ -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 @@
   /// 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 @@
   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 @@
   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 @@
   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;
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 19 18:52:42 2009
@@ -3094,10 +3094,23 @@
   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();

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jun 19 18:52:42 2009
@@ -2031,7 +2031,7 @@
   // 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 @@
     }
 
     OverloadCandidateSet::iterator Best;
-    switch (BestViableFunction(CandidateSet, Best)) {
+    switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) {
     case OR_Success:
       // This is a direct binding.
       BindsDirectly = true;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 19 18:52:42 2009
@@ -627,6 +627,7 @@
 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 @@
     // 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 @@
         = 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 @@
           // 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 @@
           // 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 @@
   // 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 @@
 
     // 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 @@
 
     // 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 @@
                                       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 @@
     *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);
+  }
+}
+

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jun 19 18:52:42 2009
@@ -546,7 +546,7 @@
 
   // 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 @@
   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],

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=73797&r1=73796&r2=73797&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jun 19 18:52:42 2009
@@ -1379,7 +1379,7 @@
   }
 
   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 @@
   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 @@
        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 @@
                                          CandidateSet);
 
   OverloadCandidateSet::iterator Best;
-  switch (BestViableFunction(CandidateSet, Best)) {
+  switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
   case OR_Success:
     return Best->Function;
 
@@ -3815,7 +3827,7 @@
 
   // 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 @@
 
   // 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 @@
     }
 
     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 @@
 
   // 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 @@
 
   // 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;

Added: cfe/trunk/test/Sema/warn-unused-parameters.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unused-parameters.c?rev=73797&view=auto

==============================================================================
--- cfe/trunk/test/Sema/warn-unused-parameters.c (added)
+++ cfe/trunk/test/Sema/warn-unused-parameters.c Fri Jun 19 18:52:42 2009
@@ -0,0 +1,13 @@
+// RUN: clang -fsyntax-only -Wunused-parameter %s -Xclang -verify
+
+int f0(int x,
+       int y, // expected-warning{{unused}}
+       int z __attribute__((unused))) {
+  return x;
+}
+
+void f1() {
+  (void)^(int x,
+          int y, // expected-warning{{unused}}
+          int z __attribute__((unused))) { return x; };
+}
\ No newline at end of file

Added: cfe/trunk/test/SemaObjC/warn-unused-parameters.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-unused-parameters.m?rev=73797&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/warn-unused-parameters.m (added)
+++ cfe/trunk/test/SemaObjC/warn-unused-parameters.m Fri Jun 19 18:52:42 2009
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only -Wunused -Xclang -verify %s
+
+ at interface foo
+- (int)meth: (int)x: (int)y: (int)z ;
+ at end
+
+ at implementation foo
+- (int) meth: (int)x: 
+              (int)y: // expected-warning{{unused}} 
+              (int) __attribute__((unused))z { return x; }
+ at end





More information about the cfe-commits mailing list