[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