[cfe-commits] r68261 - in /cfe/trunk: TODO.txt include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaTemplate.cpp test/Sema/fixit-errors.c test/Sema/fixit.c test/SemaCXX/fixit.cpp test/SemaCXX/nested-name-spec.cpp

Douglas Gregor dgregor at apple.com
Wed Apr 1 16:51:29 PDT 2009


Author: dgregor
Date: Wed Apr  1 18:51:29 2009
New Revision: 68261

URL: http://llvm.org/viewvc/llvm-project?rev=68261&view=rev
Log:
Add some more code modification hints

Added:
    cfe/trunk/test/Sema/fixit-errors.c
Modified:
    cfe/trunk/TODO.txt
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/Parser.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/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/Sema/fixit.c
    cfe/trunk/test/SemaCXX/fixit.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp

Modified: cfe/trunk/TODO.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/TODO.txt?rev=68261&r1=68260&r2=68261&view=diff

==============================================================================
--- cfe/trunk/TODO.txt (original)
+++ cfe/trunk/TODO.txt Wed Apr  1 18:51:29 2009
@@ -60,5 +60,9 @@
 remaining errors are likely to be less interesting, and (2) the poor
 user has to scroll his terminal to find out where things went wrong.
 
-
-
+//===---------------------------------------------------------------------===//
+More ideas for code modification hints:
+  - If no member of a given name is found in a class/struct, search through the names of entities that do exist in the class and suggest the closest candidate. e.g., if I write "DS.setTypeSpecType", it would suggest "DS.SetTypeSpecType" (edit distance = 1).
+  - If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
+  - Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
+  - Change "foo.bar" to "foo->bar" when "foo" is a pointer.

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr  1 18:51:29 2009
@@ -258,7 +258,7 @@
   "'virtual' can only be specified inside the class definition">;
 def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
 def err_static_out_of_line : Error<
-  "'static' can not be specified on an out-of-line static member definition">;
+  "'static' can only be specified inside the class definition">;
 def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">;
 def err_not_integral_type_bitfield : Error<
   "bit-field %0 has non-integral type %1">;
@@ -465,7 +465,7 @@
   "a parameter list without types is only allowed in a function definition">;
 def ext_param_not_declared : Extension<
   "parameter %0 was not declared, defaulting to type 'int'">;
-def ext_param_typedef_of_void : Extension<
+def err_param_typedef_of_void : Error<
   "empty parameter list defined with a typedef of 'void' not allowed in C++">;
 def err_param_default_argument : Error<
   "C does not support default arguments">;
@@ -580,8 +580,6 @@
   "%select{too few|too many}0 template arguments for "
   "%select{class template|function template|template template parameter"
   "|template}1 %2">;
-
-
 def note_template_decl_here : Note<"template is declared here">;
 def note_member_of_template_here : Note<"member is declared here">;
 def err_template_arg_must_be_type : Error<
@@ -604,11 +602,9 @@
 def err_template_arg_template_params_mismatch : Error<
   "template template argument has different template parameters than its "
   "corresponding template template parameter">;
-
 def err_template_arg_not_integral_or_enumeral : Error<
   "non-type template argument of type %0 must have an integral or enumeration"
   " type">;
-
 def err_template_arg_not_ice : Error<
   "non-type template argument of type %0 is not an integral constant "
   "expression">;
@@ -618,11 +614,9 @@
 def err_template_arg_negative : Error<
   "non-type template argument provides negative value '%0' for unsigned "
   "template parameter of type %1">;
-
 def err_template_arg_too_large : Error<
   "non-type template argument value '%0' is too large for template "
   "parameter of type %1">;
-
 def err_template_arg_no_ref_bind : Error<
   "non-type template parameter of reference type %0 cannot bind to template "
   "argument of type %1">;

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Apr  1 18:51:29 2009
@@ -268,7 +268,8 @@
   /// been parsed prior to a function definition.
   /// @param S  The function prototype scope.
   /// @param D  The function declarator.
-  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D) {
+  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                               SourceLocation LocAfterDecls) {
   }
 
   /// ActOnStartOfFunctionDef - This is called at the start of a function

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

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Apr  1 18:51:29 2009
@@ -740,7 +740,7 @@
   }
 
   // The actions module must verify that all arguments were declared.
-  Actions.ActOnFinishKNRParamDeclarations(CurScope, D);
+  Actions.ActOnFinishKNRParamDeclarations(CurScope, D, Tok.getLocation());
 }
 
 

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Apr  1 18:51:29 2009
@@ -368,7 +368,8 @@
   virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
   virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
                                                  unsigned NumDecls);
-  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D);
+  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                               SourceLocation LocAfterDecls);
   virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D);
   virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D);
   virtual void ActOnStartOfObjCMethodDef(Scope *S, DeclPtrTy D);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr  1 18:51:29 2009
@@ -2041,7 +2041,7 @@
       // typedef of void is not permitted.
       if (getLangOptions().CPlusPlus &&
           Param->getType().getUnqualifiedType() != Context.VoidTy) {
-        Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
+        Diag(Param->getLocation(), diag::err_param_typedef_of_void);
       }
     } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
       for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
@@ -2697,7 +2697,8 @@
   return DeclPtrTy::make(New);
 }
 
-void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D) {
+void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                           SourceLocation LocAfterDecls) {
   assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
          "Not a function declarator!");
   DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
@@ -2707,8 +2708,13 @@
   if (!FTI.hasPrototype) {
     for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
       if (FTI.ArgInfo[i].Param == 0) {
+        std::string Code = "int ";
+        Code += FTI.ArgInfo[i].Ident->getName();
+        Code += ";\n ";
         Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
-          << FTI.ArgInfo[i].Ident;
+          << FTI.ArgInfo[i].Ident
+          << CodeModificationHint::CreateInsertion(LocAfterDecls, Code);
+
         // Implicitly declare the argument as type 'int' for lack of a better
         // type.
         DeclSpec DS;
@@ -3215,13 +3221,29 @@
         // Make sure that this wasn't declared as an enum and now used as a
         // struct or something similar.
         if (PrevTagDecl->getTagKind() != Kind) {
-          Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
+          bool SafeToContinue 
+            = (PrevTagDecl->getTagKind() != TagDecl::TK_enum &&
+               Kind != TagDecl::TK_enum);
+          if (SafeToContinue)
+            Diag(KWLoc, diag::err_use_with_wrong_tag) 
+              << Name
+              << CodeModificationHint::CreateReplacement(SourceRange(KWLoc),
+                                                  PrevTagDecl->getKindName());
+          else
+            Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
           Diag(PrevDecl->getLocation(), diag::note_previous_use);
-          // Recover by making this an anonymous redefinition.
-          Name = 0;
-          PrevDecl = 0;
-          Invalid = true;
-        } else {
+
+          if (SafeToContinue) 
+            Kind = PrevTagDecl->getTagKind();
+          else {
+            // Recover by making this an anonymous redefinition.
+            Name = 0;
+            PrevDecl = 0;
+            Invalid = true;
+          }
+        }
+
+        if (!Invalid) {
           // If this is a use, just return the declaration we found.
 
           // FIXME: In the future, return a variant or some other clue

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr  1 18:51:29 2009
@@ -1307,8 +1307,9 @@
     QualType ParamType = Constructor->getParamDecl(0)->getType();
     QualType ClassTy = Context.getTagDeclType(ClassDecl);
     if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
-      Diag(Constructor->getLocation(), diag::err_constructor_byvalue_arg)
-        << SourceRange(Constructor->getParamDecl(0)->getLocation());
+      SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
+      Diag(ParamLoc, diag::err_constructor_byvalue_arg)
+        << CodeModificationHint::CreateInsertion(ParamLoc, "const &");
       Invalid = true;
     }
   }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Apr  1 18:51:29 2009
@@ -3402,11 +3402,25 @@
     // operand is null), the user probably wants strcmp.
     if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
         !RHSStripped->isNullPointerConstant(Context))
-      Diag(Loc, diag::warn_stringcompare) << lex->getSourceRange();
+      Diag(Loc, diag::warn_stringcompare) 
+        << lex->getSourceRange()
+        << CodeModificationHint::CreateReplacement(SourceRange(Loc), ", ")
+        << CodeModificationHint::CreateInsertion(lex->getLocStart(),
+                                                 "strcmp(")
+        << CodeModificationHint::CreateInsertion(
+                                       PP.getLocForEndOfToken(rex->getLocEnd()),
+                                       ") == 0");
     else if ((isa<StringLiteral>(RHSStripped) ||
               isa<ObjCEncodeExpr>(RHSStripped)) &&
              !LHSStripped->isNullPointerConstant(Context))
-      Diag(Loc, diag::warn_stringcompare) << rex->getSourceRange();
+      Diag(Loc, diag::warn_stringcompare) 
+        << rex->getSourceRange()
+        << CodeModificationHint::CreateReplacement(SourceRange(Loc), ", ")
+        << CodeModificationHint::CreateInsertion(lex->getLocStart(),
+                                                 "strcmp(")
+        << CodeModificationHint::CreateInsertion(
+                                       PP.getLocForEndOfToken(rex->getLocEnd()),
+                                       ") == 0");
   }
 
   // The result of comparisons is 'bool' in C++, 'int' in C.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Apr  1 18:51:29 2009
@@ -540,7 +540,9 @@
 
   if (T->isScalarType())
     SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
-      << IList->getSourceRange();
+      << IList->getSourceRange()
+      << CodeModificationHint::CreateRemoval(SourceRange(IList->getLocStart()))
+      << CodeModificationHint::CreateRemoval(SourceRange(IList->getLocEnd()));
 }
 
 void InitListChecker::CheckListElementTypes(InitListExpr *IList,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr  1 18:51:29 2009
@@ -462,12 +462,14 @@
     //   template declaration (7.1.5.3).
     RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
     if (PrevRecordDecl->getTagKind() != Kind) {
-      Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
+      Diag(KWLoc, diag::err_use_with_wrong_tag) 
+        << Name
+        << CodeModificationHint::CreateReplacement(KWLoc, 
+                            PrevRecordDecl->getKindName());
       Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
-      return true;
+      Kind = PrevRecordDecl->getTagKind();
     }
 
-
     // Check for redefinition of this class template.
     if (TK == TK_Definition) {
       if (TagDecl *Def = PrevRecordDecl->getDefinition(Context)) {
@@ -1974,7 +1976,10 @@
   case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
   }
   if (ClassTemplate->getTemplatedDecl()->getTagKind() != Kind) {
-    Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate;
+    Diag(KWLoc, diag::err_use_with_wrong_tag) 
+      << ClassTemplate
+      << CodeModificationHint::CreateReplacement(KWLoc, 
+                            ClassTemplate->getTemplatedDecl()->getKindName());
     Diag(ClassTemplate->getTemplatedDecl()->getLocation(), 
          diag::note_previous_use);
     Kind = ClassTemplate->getTemplatedDecl()->getTagKind();

Added: cfe/trunk/test/Sema/fixit-errors.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/fixit-errors.c?rev=68261&view=auto

==============================================================================
--- cfe/trunk/test/Sema/fixit-errors.c (added)
+++ cfe/trunk/test/Sema/fixit-errors.c Wed Apr  1 18:51:29 2009
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s 
+
+/* This is a test of the various code modification hints that are
+   provided as part of warning or extension diagnostics. Eventually,
+   we would like to actually try to perform the suggested
+   modifications and compile the result to test that no warnings
+   remain. */
+struct s; // expected-note{{previous use is here}}
+
+union s *s1; // expected-error{{use of 's' with tag type that does not match previous declaration}}

Modified: cfe/trunk/test/Sema/fixit.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/fixit.c?rev=68261&r1=68260&r2=68261&view=diff

==============================================================================
--- cfe/trunk/test/Sema/fixit.c (original)
+++ cfe/trunk/test/Sema/fixit.c Wed Apr  1 18:51:29 2009
@@ -16,3 +16,14 @@
 
 struct s s0 = { y: 5 };
 int array0[5] = { [3] 3 };
+
+void f1(x, y) 
+{
+}
+
+int i0 = { 17 };
+
+int f2(const char *my_string) {
+  // FIXME: terminal output isn't so good when "my_string" is shorter
+  return my_string == "foo";
+}

Modified: cfe/trunk/test/SemaCXX/fixit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/fixit.cpp?rev=68261&r1=68260&r2=68261&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/fixit.cpp (original)
+++ cfe/trunk/test/SemaCXX/fixit.cpp Wed Apr  1 18:51:29 2009
@@ -6,9 +6,25 @@
    modifications and compile the result to test that no warnings
    remain. */
 
-struct C1 { };
+struct C1 { 
+  virtual void f();
+  static void g();
+};
 struct C2 : virtual public virtual C1 { }; // expected-error{{duplicate}}
 
-template<int Value> struct CT { };
+virtual void C1::f() { } // expected-error{{'virtual' can only be specified inside the class definition}}
+
+static void C1::g() { } // expected-error{{'static' can only be specified inside the class definition}}
+
+template<int Value> struct CT { }; // expected-note{{previous use is here}}
 
 CT<10 >> 2> ct; // expected-warning{{require parentheses}}
+
+class C3 {
+public:
+  C3(C3, int i = 0); // expected-error{{copy constructor must pass its first argument by reference}}
+};
+
+struct CT<0> { }; // expected-error{{'template<>'}}
+
+template<> class CT<1> { }; // expected-error{{tag type}}

Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=68261&r1=68260&r2=68261&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Wed Apr  1 18:51:29 2009
@@ -18,12 +18,12 @@
 
 int A::C::Ag1() { return 0; }
 
-static int A::C::Ag2() { return 0; } // expected-error{{'static' can not be specified on an out-of-line static member}}
+static int A::C::Ag2() { return 0; } // expected-error{{'static' can}}
 
 int A::C::cx = 17;
 
 
-static int A::C::cx2 = 17; // expected-error{{'static' can not be specified on an out-of-line static member}}
+static int A::C::cx2 = 17; // expected-error{{'static' can}}
 
 class C2 {
   void m(); // expected-note{{member declaration nearly matches}}





More information about the cfe-commits mailing list