[cfe-commits] r98684 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Decl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp

John McCall rjmccall at apple.com
Tue Mar 16 14:48:18 PDT 2010


Author: rjmccall
Date: Tue Mar 16 16:48:18 2010
New Revision: 98684

URL: http://llvm.org/viewvc/llvm-project?rev=98684&view=rev
Log:
Implement -Wshadow.  Based on a patch by Mike M.!


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=98684&r1=98683&r2=98684&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Mar 16 16:48:18 2010
@@ -73,7 +73,7 @@
 def ReturnType : DiagGroup<"return-type">;
 def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
 def : DiagGroup<"sequence-point">;
-def : DiagGroup<"shadow">;
+def Shadow : DiagGroup<"shadow">;
 def : DiagGroup<"shorten-64-to-32">;
 def SignCompare : DiagGroup<"sign-compare">;
 def : DiagGroup<"synth">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=98684&r1=98683&r2=98684&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 16 16:48:18 2010
@@ -107,7 +107,16 @@
   "use of out-of-scope declaration of %0">;
 def err_inline_non_function : Error<
   "'inline' can only appear on functions">;
-  
+
+def warn_decl_shadow :
+  Warning<"declaration shadows a %select{"
+          "local variable|"
+          "variable in %2|"
+          "static data member of %2|"
+          "field of %2|"
+          "global built-in function}1">,
+  InGroup<Shadow>, DefaultIgnore;
+
 // C++ using declarations
 def err_using_requires_qualname : Error<
   "using declaration requires a qualified name">;

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=98684&r1=98683&r2=98684&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Mar 16 16:48:18 2010
@@ -430,7 +430,10 @@
   for (; I!=End; ++I)
     QualName += *I + "::";
 
-  QualName += getNameAsString();
+  if (getDeclName())
+    QualName += getNameAsString();
+  else
+    QualName += "<anonymous>";
 
   return QualName;
 }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=98684&r1=98683&r2=98684&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 16 16:48:18 2010
@@ -778,6 +778,7 @@
                                         const LookupResult &Previous,
                                         Scope *S);
   void DiagnoseFunctionSpecifiers(Declarator& D);
+  void DiagnoseShadow(NamedDecl* D, const LookupResult& R);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     QualType R, TypeSourceInfo *TInfo,
                                     LookupResult &Previous, bool &Redeclaration);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=98684&r1=98683&r2=98684&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 16 16:48:18 2010
@@ -2403,6 +2403,9 @@
     NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
   }
 
+  // Diagnose shadowed variables before filtering for scope.
+  DiagnoseShadow(NewVD, Previous);
+
   // Don't consider existing declarations that are in a different
   // scope and are out-of-semantic-context declarations (if the new
   // declaration has linkage).
@@ -2454,6 +2457,65 @@
   return NewVD;
 }
 
+/// \brief Diagnose variable or built-in function shadowing.
+///
+/// This method is called as soon as a NamedDecl materializes to check
+/// if it shadows another local or global variable, or a built-in function.
+///
+/// For performance reasons, the lookup results are reused from the calling
+/// context.
+///
+/// \param D variable decl to diagnose. Must be a variable.
+/// \param R cached previous lookup of \p D.
+///
+void Sema::DiagnoseShadow(NamedDecl* D, const LookupResult& R) {
+  assert(D->getKind() == Decl::Var && "Expecting variable.");
+
+  // Return if warning is ignored.
+  if (Diags.getDiagnosticLevel(diag::warn_decl_shadow) == Diagnostic::Ignored)
+    return;
+
+  // Return if not local decl.
+  if (!D->getDeclContext()->isFunctionOrMethod())
+    return;
+
+  DeclarationName Name = D->getDeclName();
+
+  // Return if lookup has no result.
+  if (R.getResultKind() != LookupResult::Found) {
+    // Emit warning for built-in shadowing.
+    if (Name.getAsIdentifierInfo() &&
+        Name.getAsIdentifierInfo()->getBuiltinID())
+      Diag(D->getLocation(), diag::warn_decl_shadow)
+        << Name
+        << 4 // global builtin
+        << Context.getTranslationUnitDecl();
+    return;
+  }
+
+  // Return if not variable decl.
+  NamedDecl* ShadowedDecl = R.getFoundDecl();
+  if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
+    return;
+
+  // Determine kind of declaration.
+  DeclContext *DC = ShadowedDecl->getDeclContext();
+  unsigned Kind;
+  if (isa<RecordDecl>(DC)) {
+    if (isa<FieldDecl>(ShadowedDecl))
+      Kind = 3; // field
+    else
+      Kind = 2; // static data member
+  } else if (DC->isFileContext())
+    Kind = 1; // global
+  else
+    Kind = 0; // local
+
+  // Emit warning and note.
+  Diag(D->getLocation(), diag::warn_decl_shadow) << Name << Kind << DC;
+  Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
+}
+
 /// \brief Perform semantic checking on a newly-created variable
 /// declaration.
 ///





More information about the cfe-commits mailing list