forked from OSchip/llvm-project
Add a new expression classification, CL_AddressableVoid
CL_AddressableVoid is the expression classification used for void expressions whose address can be taken, i.e. the result of [], * or void variable references in C, as opposed to things like the result of a void function call. llvm-svn: 129783
This commit is contained in:
parent
9ef4563c2a
commit
133587f08b
|
@ -221,6 +221,7 @@ public:
|
|||
CL_XValue,
|
||||
CL_Function, // Functions cannot be lvalues in C.
|
||||
CL_Void, // Void cannot be an lvalue in C.
|
||||
CL_AddressableVoid, // Void expression whose address can be taken in C.
|
||||
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
|
||||
CL_MemberFunction, // An expression referring to a member function
|
||||
CL_SubObjCPropertySetting,
|
||||
|
|
|
@ -61,8 +61,10 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
|
|||
if (TR->isFunctionType() || TR == Ctx.OverloadTy)
|
||||
kind = Cl::CL_Function;
|
||||
// No void either, but qualified void is OK because it is "other than void".
|
||||
else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
|
||||
kind = Cl::CL_Void;
|
||||
// Void "lvalues" are classified as addressable void values, which are void
|
||||
// expressions whose address can be taken.
|
||||
else if (TR->isVoidType() && !TR.hasQualifiers())
|
||||
kind = (kind == Cl::CL_LValue ? Cl::CL_AddressableVoid : Cl::CL_Void);
|
||||
}
|
||||
|
||||
// Enable this assertion for testing.
|
||||
|
@ -71,6 +73,7 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
|
|||
case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break;
|
||||
case Cl::CL_Function:
|
||||
case Cl::CL_Void:
|
||||
case Cl::CL_AddressableVoid:
|
||||
case Cl::CL_DuplicateVectorComponents:
|
||||
case Cl::CL_MemberFunction:
|
||||
case Cl::CL_SubObjCPropertySetting:
|
||||
|
@ -563,7 +566,8 @@ Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const {
|
|||
case Cl::CL_LValue: return LV_Valid;
|
||||
case Cl::CL_XValue: return LV_InvalidExpression;
|
||||
case Cl::CL_Function: return LV_NotObjectType;
|
||||
case Cl::CL_Void: return LV_IncompleteVoidType;
|
||||
case Cl::CL_Void: return LV_InvalidExpression;
|
||||
case Cl::CL_AddressableVoid: return LV_IncompleteVoidType;
|
||||
case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents;
|
||||
case Cl::CL_MemberFunction: return LV_MemberFunction;
|
||||
case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
|
||||
|
@ -582,7 +586,8 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
|
|||
case Cl::CL_LValue: break;
|
||||
case Cl::CL_XValue: return MLV_InvalidExpression;
|
||||
case Cl::CL_Function: return MLV_NotObjectType;
|
||||
case Cl::CL_Void: return MLV_IncompleteVoidType;
|
||||
case Cl::CL_Void: return MLV_InvalidExpression;
|
||||
case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType;
|
||||
case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
|
||||
case Cl::CL_MemberFunction: return MLV_MemberFunction;
|
||||
case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
|
||||
|
|
|
@ -107,3 +107,14 @@ char* f7() {
|
|||
|
||||
void* t3 = &(*(void*)0);
|
||||
}
|
||||
|
||||
void f8() {
|
||||
void *dummy0 = &f8(); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
|
||||
extern void v;
|
||||
void *dummy1 = &(1 ? v : f8()); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
|
||||
void *dummy2 = &(f8(), v); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
|
||||
void *dummy3 = &({ ; }); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue