forked from OSchip/llvm-project
Fix handling of implicit int, resolving PR2012 and reverting (and
subsuming) my patch for PR1999. llvm-svn: 49251
This commit is contained in:
parent
94fc8063b4
commit
9d51f2b9d4
|
@ -400,6 +400,10 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
|
||||
Options.ImplicitInt = 1;
|
||||
else
|
||||
Options.ImplicitInt = 0;
|
||||
Options.Trigraphs = 1; // -trigraphs or -ansi
|
||||
Options.DollarIdents = 1; // FIXME: Really a target property.
|
||||
Options.PascalStrings = PascalStrings;
|
||||
|
|
|
@ -257,6 +257,11 @@ DIAG(ext_top_level_semi, EXTENSION,
|
|||
"ISO C does not allow an extra ';' outside of a function")
|
||||
DIAG(ext_extra_struct_semi, EXTENSION,
|
||||
"ISO C does not allow an extra ';' inside a struct or union")
|
||||
DIAG(ext_missing_declspec, EXTENSION,
|
||||
"declaration specifier missing, defaulting to 'int'")
|
||||
DIAG(ext_missing_type_specifier, EXTENSION,
|
||||
"type specifier missing, defaults to 'int'")
|
||||
|
||||
DIAG(ext_duplicate_declspec, EXTENSION,
|
||||
"duplicate '%0' declaration specifier")
|
||||
DIAG(ext_plain_complex, EXTENSION,
|
||||
|
@ -539,8 +544,6 @@ DIAG(err_invalid_storage_class_in_func_decl, ERROR,
|
|||
"invalid storage class specifier in function declarator")
|
||||
DIAG(ext_anon_param_requires_type_specifier, EXTENSION,
|
||||
"type specifier required for unnamed parameter, defaults to int")
|
||||
DIAG(ext_param_requires_type_specifier, EXTENSION,
|
||||
"type specifier required for parameter '%0', defaults to int")
|
||||
DIAG(err_missing_param, ERROR,
|
||||
"expected parameter declarator")
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ namespace clang {
|
|||
/// enabled, which controls the dialect of C that is accepted.
|
||||
struct LangOptions {
|
||||
unsigned Trigraphs : 1; // Trigraphs in source files.
|
||||
unsigned BCPLComment : 1; // BCPL-style // comments.
|
||||
unsigned BCPLComment : 1; // BCPL-style '//' comments.
|
||||
unsigned DollarIdents : 1; // '$' allowed in identifiers.
|
||||
unsigned ImplicitInt : 1; // C89 implicit 'int'.
|
||||
unsigned Digraphs : 1; // C94, C99 and C++
|
||||
unsigned HexFloats : 1; // C99 Hexadecimal float constants.
|
||||
unsigned C99 : 1; // C99 Support
|
||||
|
@ -42,15 +43,14 @@ struct LangOptions {
|
|||
unsigned LaxVectorConversions : 1;
|
||||
|
||||
LangOptions() {
|
||||
Trigraphs = BCPLComment = DollarIdents = Digraphs = HexFloats = 0;
|
||||
Trigraphs = BCPLComment = DollarIdents = ImplicitInt = Digraphs = 0;
|
||||
HexFloats = 0;
|
||||
ObjC1 = ObjC2 = 0;
|
||||
C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
|
||||
CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
|
||||
LaxVectorConversions = 0;
|
||||
}
|
||||
|
||||
bool isC90() const { return !C99 && !CPlusPlus; }
|
||||
|
||||
/// Emit - Emit this LangOptions object to bitcode.
|
||||
void Emit(llvm::Serializer& S) const;
|
||||
|
||||
|
|
|
@ -664,7 +664,7 @@ public:
|
|||
AttributeList *getAttributes() const { return AttrList; }
|
||||
|
||||
void setInvalidType(bool flag) { InvalidType = flag; }
|
||||
bool getInvalidType() { return InvalidType; }
|
||||
bool getInvalidType() const { return InvalidType; }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -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.
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -6,7 +6,7 @@ void f0();
|
|||
void f1(int [*]);
|
||||
void f2(int [const *]);
|
||||
void f3(int [volatile const*]);
|
||||
int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier required}} */
|
||||
int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier missing, defaults to 'int'}} */
|
||||
|
||||
char ((((*X))));
|
||||
|
||||
|
|
|
@ -36,6 +36,14 @@ int *__restrict; /* expected-error {{expected identifier}} */
|
|||
|
||||
|
||||
/* Implicit int, always ok */
|
||||
foo() {}
|
||||
test6() {}
|
||||
|
||||
/* PR2012 */
|
||||
test7; /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
|
||||
|
||||
void test8(int, x); /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
|
||||
|
||||
typedef int sometype;
|
||||
int a(sometype, y) {return 0;} /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ void h (const char *fmt, ...) {} //expected-error{{conflicting types for 'h'}}
|
|||
|
||||
// PR1965
|
||||
int t5(b); // expected-error {{parameter list without types}}
|
||||
int t6(int x, g); // expected-warning {{type specifier required for parameter 'g'}}
|
||||
int t6(int x, g); // expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
|
||||
int t7(, ); // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}}
|
||||
int t8(, int a); // expected-error {{expected parameter declarator}}
|
||||
|
|
Loading…
Reference in New Issue