change implicit int warnings to point to the identifier, not the

start of the declspec.  The fixit still goes there, and we underline
the declspec.  This helps when the start of the declspec came from a
macro that expanded from a system header.  For example, we now produce:

t.c:2:8: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static x;
~~~~~~ ^

llvm-svn: 69777
This commit is contained in:
Chris Lattner 2009-04-22 05:27:59 +00:00
parent 9dae596dc1
commit dc00437fa0
4 changed files with 36 additions and 21 deletions

View File

@ -371,7 +371,7 @@ public:
// Type Analysis / Processing: SemaType.cpp.
//
QualType adjustParameterType(QualType T);
QualType ConvertDeclSpecToType(const DeclSpec &DS);
QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);

View File

@ -46,9 +46,11 @@ QualType Sema::adjustParameterType(QualType T) {
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param DS the declaration specifiers
/// \param DeclLoc The location of the declarator identifier or invalid if none.
/// \returns The type described by the declaration specifiers, or NULL
/// if there was an error.
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
SourceLocation DeclLoc) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
QualType Result;
@ -101,20 +103,29 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
if (getLangOptions().ImplicitInt) {
// In C89 mode, we only warn if there is a completely missing declspec
// when one is not allowed.
if (DS.isEmpty())
Diag(DS.getSourceRange().getBegin(), diag::warn_missing_declspec)
if (DS.isEmpty()) {
if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin();
Diag(DeclLoc, diag::warn_missing_declspec)
<< DS.getSourceRange()
<< CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
"int");
}
} else if (!DS.hasTypeSpecifier()) {
// C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
// "At least one type specifier shall be given in the declaration
// specifiers in each declaration, and in the specifier-qualifier list in
// each struct declaration and type name."
// FIXME: Does Microsoft really have the implicit int extension in C++?
unsigned DK = getLangOptions().CPlusPlus && !getLangOptions().Microsoft?
diag::err_missing_type_specifier
: diag::warn_missing_type_specifier;
Diag(DS.getSourceRange().getBegin(), DK);
if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin();
if (getLangOptions().CPlusPlus && !getLangOptions().Microsoft)
Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
else
Diag(DeclLoc, diag::warn_missing_type_specifier)
<< DS.getSourceRange();
// FIXME: If we could guarantee that the result would be
// well-formed, it would be useful to have a code insertion hint
@ -183,13 +194,18 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
// id<protocol-list>
Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
DS.getNumProtocolQualifiers());
else if (Result == Context.getObjCClassType())
else if (Result == Context.getObjCClassType()) {
if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin();
// Class<protocol-list>
Diag(DS.getSourceRange().getBegin(),
diag::err_qualified_class_unsupported) << DS.getSourceRange();
else
Diag(DS.getSourceRange().getBegin(),
diag::err_invalid_protocol_qualifiers) << DS.getSourceRange();
Diag(DeclLoc, diag::err_qualified_class_unsupported)
<< DS.getSourceRange();
} else {
if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin();
Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
<< DS.getSourceRange();
}
}
// TypeQuals handled by caller.
break;
@ -592,13 +608,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
case Declarator::DK_Abstract:
case Declarator::DK_Normal:
case Declarator::DK_Operator: {
const DeclSpec& DS = D.getDeclSpec();
if (OmittedReturnType)
const DeclSpec &DS = D.getDeclSpec();
if (OmittedReturnType) {
// We default to a dependent type initially. Can be modified by
// the first return statement.
T = Context.DependentTy;
else {
T = ConvertDeclSpecToType(DS);
} else {
T = ConvertDeclSpecToType(DS, D.getIdentifierLoc());
if (T.isNull())
return T;
}

View File

@ -40,7 +40,7 @@ void test2() {
foo:
takeclosure(^{ x = 4; }); // expected-error {{variable is not assignable (missing __block type specifier)}}
__block y = 7;
__block y = 7; // expected-warning {{type specifier missing, defaults to 'int'}}
takeclosure(^{ y = 8; });
}

View File

@ -23,8 +23,7 @@ h19_insline(n) // expected-warning {{parameter 'n' was not declared, defaulting
}
struct foo {
__extension__ __attribute__((packed)) // expected-warning {{type specifier missing, defaults to 'int'}}
x : 4;
__extension__ __attribute__((packed)) x : 4; // expected-warning {{type specifier missing, defaults to 'int'}}
};