diff options
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 50 | ||||
-rw-r--r-- | test/Sema/block-literal.c | 2 | ||||
-rw-r--r-- | test/Sema/implicit-int.c | 3 |
4 files changed, 36 insertions, 21 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f3c337c148..e8c69c2f5f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index b8969a2202..50f5071306 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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; } diff --git a/test/Sema/block-literal.c b/test/Sema/block-literal.c index c6e3931aa8..19d476fc29 100644 --- a/test/Sema/block-literal.c +++ b/test/Sema/block-literal.c @@ -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; }); } diff --git a/test/Sema/implicit-int.c b/test/Sema/implicit-int.c index 90fe607e12..04b27a8f0e 100644 --- a/test/Sema/implicit-int.c +++ b/test/Sema/implicit-int.c @@ -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'}} }; |