mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-10 10:01:42 +00:00
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
|
// Otherwise, we have a function with an argument list that is
|
||||||
// potentially variadic.
|
// potentially variadic.
|
||||||
SmallVector<TypeRef, 16> ArgTys;
|
SmallVector<TypeRef, 16> ArgTys;
|
||||||
|
|
||||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
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.
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,14 @@ using namespace clang;
|
|||||||
|
|
||||||
Type::~Type() {}
|
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
|
// Type Printing
|
||||||
|
@ -1020,28 +1020,6 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||||||
DS.ClearStorageClassSpecs();
|
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
|
// Inform the actions module about the parameter declarator, so it gets
|
||||||
// added to the current scope.
|
// added to the current scope.
|
||||||
Action::TypeResult ParamTy =
|
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
|
// Otherwise, we have a function with an argument list that is
|
||||||
// potentially variadic.
|
// potentially variadic.
|
||||||
SmallVector<TypeRef, 16> ArgTys;
|
SmallVector<TypeRef, 16> ArgTys;
|
||||||
|
|
||||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
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.
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,10 @@ public:
|
|||||||
bool isCanonical() const { return CanonicalType == this; }
|
bool isCanonical() const { return CanonicalType == this; }
|
||||||
Type *getCanonicalType() const { return CanonicalType; }
|
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;
|
virtual void getAsString(std::string &InnerString) const = 0;
|
||||||
|
|
||||||
static bool classof(const Type *) { return true; }
|
static bool classof(const Type *) { return true; }
|
||||||
@ -179,6 +183,8 @@ class BuiltinType : public Type {
|
|||||||
public:
|
public:
|
||||||
BuiltinType(const char *name) : Type(Builtin, 0), Name(name) {}
|
BuiltinType(const char *name) : Type(Builtin, 0), Name(name) {}
|
||||||
|
|
||||||
|
const char *getName() const { return Name; }
|
||||||
|
|
||||||
virtual void getAsString(std::string &InnerString) const;
|
virtual void getAsString(std::string &InnerString) const;
|
||||||
|
|
||||||
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
|
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
|
||||||
|
21
clang/test/Sema/void_arg.c
Normal file
21
clang/test/Sema/void_arg.c
Normal file
@ -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
Block a user