Add some more code modification hints

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68261 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c442b84..f9270cf 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e02e2ee..f67b417 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index ea2af68..c2928dc 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
     }
   }
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7a25404..1540f0a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index fbf3ae2..f8890c3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -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,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index abc3ac0..d30726c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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();