diff options
author | Chris Lattner <sabre@nondot.org> | 2008-04-05 06:32:51 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-04-05 06:32:51 +0000 |
commit | 9d51f2b9d44563a57aae5e5989c80dda8cde1d58 (patch) | |
tree | 745bf6d782d5106853716d53d1cf25c76ed63a59 /clang/lib | |
parent | 94fc8063b4e4635bd18ea2b9cf76b4a71685b5ca (diff) | |
download | bcm5719-llvm-9d51f2b9d44563a57aae5e5989c80dda8cde1d58.tar.gz bcm5719-llvm-9d51f2b9d44563a57aae5e5989c80dda8cde1d58.zip |
Fix handling of implicit int, resolving PR2012 and reverting (and
subsuming) my patch for PR1999.
llvm-svn: 49251
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 26 |
3 files changed, 39 insertions, 23 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7d15e984ee6..9b8ecf8bd39 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1340,7 +1340,6 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParmDecl.AddAttributes(ParseAttributes()); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. - // NOTE: we could trivially allow 'int foo(auto int X)' if we wanted. if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && DS.getStorageClassSpec() != DeclSpec::SCS_register) { Diag(DS.getStorageClassSpecLoc(), @@ -1353,11 +1352,6 @@ void Parser::ParseParenDeclarator(Declarator &D) { DS.ClearStorageClassSpecs(); } - // Inform the actions module about the parameter declarator, so it gets - // added to the current scope. - Action::TypeResult ParamTy = - Actions.ActOnParamDeclaratorType(CurScope, ParmDecl); - // Remember this parsed parameter in ParamInfo. IdentifierInfo *ParmII = ParmDecl.getIdentifier(); @@ -1366,28 +1360,28 @@ void Parser::ParseParenDeclarator(Declarator &D) { Diag(ParmDecl.getIdentifierLoc(), diag::err_param_redefinition, ParmII->getName()); ParmII = 0; + ParmDecl.setInvalidType(true); } // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. if (DS.getParsedSpecifiers() == DeclSpec::PQ_None && ParmDecl.getIdentifier() == 0 && ParmDecl.getNumTypeObjects() == 0) { + // Completely missing, emit error. Diag(DSStart, diag::err_missing_param); - } else if (!DS.hasTypeSpecifier() && - (getLang().C99 || getLang().CPlusPlus)) { - // Otherwise, if something was specified but a type specifier wasn't, - // (e.g. "x" or "restrict x" or "restrict"), this is a use of implicit - // int. This is valid in C90, but not in C99 or C++. - if (ParmII) - Diag(ParmDecl.getIdentifierLoc(), - diag::ext_param_requires_type_specifier, ParmII->getName()); - else - Diag(DSStart, diag::ext_anon_param_requires_type_specifier); - } + } else { + // Otherwise, we have something. Add it and let semantic analysis try + // to grok it and add the result to the ParamInfo we are building. - ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, - ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(), - ParmDecl.getDeclSpec().TakeAttributes())); + // Inform the actions module about the parameter declarator, so it gets + // added to the current scope. + Action::TypeResult ParamTy = + Actions.ActOnParamDeclaratorType(CurScope, ParmDecl); + + ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, + ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(), + ParmDecl.getDeclSpec().TakeAttributes())); + } // If the next token is a comma, consume it and keep reading arguments. if (Tok.isNot(tok::comma)) break; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 76091245b55..cd99fc04ebe 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -467,7 +467,7 @@ Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) { // If this is C90 and the declspecs were completely missing, fudge in an // implicit int. We do this here because this is the only place where // declaration-specifiers are completely optional in the grammar. - if (getLang().isC90() && !D.getDeclSpec().getParsedSpecifiers() == 0) { + if (getLang().ImplicitInt && D.getDeclSpec().getParsedSpecifiers() == 0) { const char *PrevSpec; D.getDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(), PrevSpec); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ca56c56dd9a..d46e9975677 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -27,7 +27,7 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) { QualType Result; switch (DS.getTypeSpecType()) { - default: return QualType(); // FIXME: Handle unimp cases! + default: assert(0 && "Unknown TypeSpecType!"); case DeclSpec::TST_void: Result = Context.VoidTy; break; @@ -42,7 +42,29 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) { Result = Context.UnsignedCharTy; } break; - case DeclSpec::TST_unspecified: // Unspecific typespec defaults to int. + case DeclSpec::TST_unspecified: + // Unspecified typespec defaults to int in C90. However, the C90 grammar + // [C90 6.5] only allows a decl-spec if there was *some* type-specifier, + // type-qualifier, or storage-class-specifier. If not, emit an extwarn. + // Note that the one exception to this is function definitions, which are + // allowed to be completely missing a declspec. This is handled in the + // parser already though by it pretending to have seen an 'int' in this + // case. + if (getLangOptions().ImplicitInt) { + if ((DS.getParsedSpecifiers() & (DeclSpec::PQ_StorageClassSpecifier | + DeclSpec::PQ_TypeSpecifier | + DeclSpec::PQ_TypeQualifier)) == 0) + Diag(DS.getSourceRange().getBegin(), diag::ext_missing_declspec); + } else { + // 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." + if (!DS.hasTypeSpecifier()) + Diag(DS.getSourceRange().getBegin(), diag::ext_missing_type_specifier); + } + + // FALL THROUGH. case DeclSpec::TST_int: { if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { switch (DS.getTypeSpecWidth()) { |