aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaType.cpp50
-rw-r--r--test/Sema/block-literal.c2
-rw-r--r--test/Sema/implicit-int.c3
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'}}
};