forked from OSchip/llvm-project
move void argument checking from the parser to the semantic analysis stage.
This allows us to handle typedefs of void correctly. This implements clang/test/Sema/void_arg.c llvm-svn: 39236
This commit is contained in:
parent
d2e97c1f80
commit
c81f079d7e
|
@ -137,12 +137,36 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||
// Otherwise, we have a function with an argument list that is
|
||||
// potentially variadic.
|
||||
SmallVector<TypeRef, 16> ArgTys;
|
||||
|
||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
||||
if (FTI.ArgInfo[i].TypeInfo == 0)
|
||||
TypeRef ArgTy = TypeRef::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo);
|
||||
if (ArgTy.isNull())
|
||||
return TypeRef(); // Error occurred parsing argument type.
|
||||
ArgTys.push_back(TypeRef::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo));
|
||||
|
||||
// Look for 'void'. void is allowed only as a single argument to a
|
||||
// function with no other parameters (C99 6.7.5.3p10). We record
|
||||
// int(void) as a FunctionTypeProto with an empty argument list.
|
||||
if (ArgTy->isVoidType()) {
|
||||
// If this is something like 'float(int, void)', reject it.
|
||||
if (FTI.NumArgs != 1 || FTI.isVariadic) {
|
||||
Diag(DeclType.Loc, diag::err_void_only_param);
|
||||
return TypeRef();
|
||||
}
|
||||
// Reject 'int(void abc)'.
|
||||
if (FTI.ArgInfo[i].Ident) {
|
||||
Diag(FTI.ArgInfo[i].IdentLoc,
|
||||
diag::err_void_param_with_identifier);
|
||||
return TypeRef();
|
||||
}
|
||||
|
||||
// Do not add 'void' to the ArgTys list.
|
||||
break;
|
||||
}
|
||||
|
||||
ArgTys.push_back(ArgTy);
|
||||
}
|
||||
T = Context.getFunctionType(T, &ArgTys[0], FTI.NumArgs, FTI.isVariadic);
|
||||
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
|
||||
FTI.isVariadic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,14 @@ using namespace clang;
|
|||
|
||||
Type::~Type() {}
|
||||
|
||||
/// isVoidType - Helper method to determine if this is the 'void' type.
|
||||
bool Type::isVoidType() const {
|
||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(getCanonicalType())) {
|
||||
// FIXME: USE ENUMS!
|
||||
return !strcmp(BT->getName(), "void");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Printing
|
||||
|
|
|
@ -1020,28 +1020,6 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||
DS.ClearStorageClassSpecs();
|
||||
}
|
||||
|
||||
|
||||
// Look for 'void'. void is allowed only as a single argument to a
|
||||
// function with no other parameters (C99 6.7.5.3p10).
|
||||
if (ParmDecl.getNumTypeObjects() == 0 && // not void*.
|
||||
DS.getTypeSpecType() == DeclSpec::TST_void) {
|
||||
if (ParmDecl.getIdentifier()) {
|
||||
Diag(ParmDecl.getIdentifierLoc(),
|
||||
diag::err_void_param_with_identifier);
|
||||
ErrorEmitted = true;
|
||||
}
|
||||
if (!ErrorEmitted &&
|
||||
(!ParamInfo.empty() || Tok.getKind() != tok::r_paren)) {
|
||||
Diag(DS.getTypeSpecTypeLoc(), diag::err_void_only_param);
|
||||
ErrorEmitted = true;
|
||||
}
|
||||
|
||||
// We know now that we either emitted an error or that the next token
|
||||
// is a ')'. Exit this loop with an empty ParamInfo list, instead of
|
||||
// adding void explicitly to the list.
|
||||
break;
|
||||
}
|
||||
|
||||
// Inform the actions module about the parameter declarator, so it gets
|
||||
// added to the current scope.
|
||||
Action::TypeResult ParamTy =
|
||||
|
|
|
@ -137,12 +137,36 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||
// Otherwise, we have a function with an argument list that is
|
||||
// potentially variadic.
|
||||
SmallVector<TypeRef, 16> ArgTys;
|
||||
|
||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
||||
if (FTI.ArgInfo[i].TypeInfo == 0)
|
||||
TypeRef ArgTy = TypeRef::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo);
|
||||
if (ArgTy.isNull())
|
||||
return TypeRef(); // Error occurred parsing argument type.
|
||||
ArgTys.push_back(TypeRef::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo));
|
||||
|
||||
// Look for 'void'. void is allowed only as a single argument to a
|
||||
// function with no other parameters (C99 6.7.5.3p10). We record
|
||||
// int(void) as a FunctionTypeProto with an empty argument list.
|
||||
if (ArgTy->isVoidType()) {
|
||||
// If this is something like 'float(int, void)', reject it.
|
||||
if (FTI.NumArgs != 1 || FTI.isVariadic) {
|
||||
Diag(DeclType.Loc, diag::err_void_only_param);
|
||||
return TypeRef();
|
||||
}
|
||||
// Reject 'int(void abc)'.
|
||||
if (FTI.ArgInfo[i].Ident) {
|
||||
Diag(FTI.ArgInfo[i].IdentLoc,
|
||||
diag::err_void_param_with_identifier);
|
||||
return TypeRef();
|
||||
}
|
||||
|
||||
// Do not add 'void' to the ArgTys list.
|
||||
break;
|
||||
}
|
||||
|
||||
ArgTys.push_back(ArgTy);
|
||||
}
|
||||
T = Context.getFunctionType(T, &ArgTys[0], FTI.NumArgs, FTI.isVariadic);
|
||||
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
|
||||
FTI.isVariadic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,10 @@ public:
|
|||
bool isCanonical() const { return CanonicalType == this; }
|
||||
Type *getCanonicalType() const { return CanonicalType; }
|
||||
|
||||
/// isVoidType - Helper method to determine if this is the 'void' type.
|
||||
bool isVoidType() const;
|
||||
|
||||
|
||||
virtual void getAsString(std::string &InnerString) const = 0;
|
||||
|
||||
static bool classof(const Type *) { return true; }
|
||||
|
@ -179,6 +183,8 @@ class BuiltinType : public Type {
|
|||
public:
|
||||
BuiltinType(const char *name) : Type(Builtin, 0), Name(name) {}
|
||||
|
||||
const char *getName() const { return Name; }
|
||||
|
||||
virtual void getAsString(std::string &InnerString) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* RUN: clang -parse-ast %s 2>&1 | grep '6 diagnostics'
|
||||
*/
|
||||
|
||||
typedef void Void;
|
||||
|
||||
void foo() {
|
||||
int X;
|
||||
|
||||
X = sizeof(int (void a));
|
||||
X = sizeof(int (int, void));
|
||||
X = sizeof(int (void, ...));
|
||||
|
||||
X = sizeof(int (Void a));
|
||||
X = sizeof(int (int, Void));
|
||||
X = sizeof(int (Void, ...));
|
||||
|
||||
// Accept these.
|
||||
X = sizeof(int (void));
|
||||
X = sizeof(int (Void));
|
||||
}
|
||||
|
Loading…
Reference in New Issue