Add code modification hints to various parsing-related diagnostics.

Plus, reword a extension warnings to avoid talking about "ISO C" when
the extension might also be available in C++ or C++0x. 



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68257 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-04-01 22:41:11 +00:00
Родитель 31a19b6989
Коммит 9b3064b55f
9 изменённых файлов: 71 добавлений и 19 удалений

Просмотреть файл

@ -17,15 +17,15 @@ def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">;
def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
def ext_top_level_semi : Extension<
"ISO C does not allow an extra ';' outside of a function">;
"extra ';' outside of a function">;
def ext_extra_struct_semi : Extension<
"ISO C does not allow an extra ';' inside a struct or union">;
"extra ';' inside a struct or union">;
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_plain_complex : Extension<
"ISO C does not support plain '_Complex' meaning '_Complex double'">;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
def ext_integer_complex : Extension<
"ISO C does not support complex integer types">;
"complex integer types are an extension">;
def ext_thread_before : Extension<"'__thread' before 'static'">;
def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">;
@ -43,8 +43,8 @@ def ext_c99_variable_decl_in_for_loop : Extension<
"variable declaration in for loop is a C99-specific feature">;
def ext_c99_compound_literal : Extension<
"compound literals are a C99-specific feature">;
def ext_c99_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a C99-specific feature">;
def ext_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a %select{C99|C++0x}0-specific feature">;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">;

Просмотреть файл

@ -324,7 +324,7 @@ public:
/// Finish - This does final analysis of the declspec, issuing diagnostics for
/// things like "_Imaginary" (lacking an FP type). After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang);
void Finish(Diagnostic &D, Preprocessor &PP);
/// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
/// without a Declarator. Only tag declspecs can stand alone.

Просмотреть файл

@ -13,6 +13,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
#include <cstring>
@ -283,9 +284,9 @@ bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
void DeclSpec::Finish(Diagnostic &D, SourceManager& SrcMgr,
const LangOptions &Lang) {
void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
// Check the type specifier components first.
SourceManager &SrcMgr = PP.getSourceManager();
// signed/unsigned are only valid with int/char/wchar_t.
if (TypeSpecSign != TSS_unspecified) {
@ -330,7 +331,10 @@ void DeclSpec::Finish(Diagnostic &D, SourceManager& SrcMgr,
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
if (TypeSpecType == TST_unspecified) {
Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex);
Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex)
<< CodeModificationHint::CreateInsertion(
PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
" double");
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
// Note that this intentionally doesn't include _Complex _Bool.

Просмотреть файл

@ -496,7 +496,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DoneWithDeclSpec:
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
DS.Finish(Diags, PP.getSourceManager(), getLang());
DS.Finish(Diags, PP);
return;
case tok::coloncolon: // ::foo::bar
@ -1169,7 +1169,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi);
Diag(Tok, diag::ext_extra_struct_semi)
<< CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
continue;
}
@ -1372,8 +1373,11 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
break;
SourceLocation CommaLoc = ConsumeToken();
if (Tok.isNot(tok::identifier) && !getLang().C99)
Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
if (Tok.isNot(tok::identifier) &&
!(getLang().C99 || getLang().CPlusPlus0x))
Diag(CommaLoc, diag::ext_enumerator_list_comma)
<< getLang().CPlusPlus
<< CodeModificationHint::CreateRemoval((SourceRange(CommaLoc)));
}
// Eat the }.
@ -1625,7 +1629,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
DoneWithTypeQuals:
// If this is not a type-qualifier token, we're done reading type
// qualifiers. First verify that DeclSpec's are consistent.
DS.Finish(Diags, PP.getSourceManager(), getLang());
DS.Finish(Diags, PP);
return;
}

Просмотреть файл

@ -608,7 +608,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
DS.Finish(Diags, PP.getSourceManager(), getLang());
DS.Finish(Diags, PP);
return;
}
if (Tok.is(tok::annot_typename))
@ -616,7 +616,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
else
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
DS.Finish(Diags, PP.getSourceManager(), getLang());
DS.Finish(Diags, PP);
}
/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++

Просмотреть файл

@ -372,7 +372,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::semi:
Diag(Tok, diag::ext_top_level_semi);
Diag(Tok, diag::ext_top_level_semi)
<< CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
return DeclGroupPtrTy();

11
test/Sema/fixit-c90.c Normal file
Просмотреть файл

@ -0,0 +1,11 @@
/* RUN: clang -fsyntax-only -std=c90 -pedantic %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. */
enum e0 {
e1,
};

18
test/Sema/fixit.c Normal file
Просмотреть файл

@ -0,0 +1,18 @@
// RUN: clang -fsyntax-only -pedantic %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. */
void f0(void) { };
struct s {
int x, y;;
};
_Complex cd;
struct s s0 = { y: 5 };
int array0[5] = { [3] 3 };

14
test/SemaCXX/fixit.cpp Normal file
Просмотреть файл

@ -0,0 +1,14 @@
// 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 C1 { };
struct C2 : virtual public virtual C1 { }; // expected-error{{duplicate}}
template<int Value> struct CT { };
CT<10 >> 2> ct; // expected-warning{{require parentheses}}