aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h1
-rw-r--r--lib/AST/ExprClassification.cpp13
-rw-r--r--test/Sema/expr-address-of.c11
3 files changed, 21 insertions, 4 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 472de76eb8..6b616c28b3 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -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,
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 803bc561ba..0d01880414 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -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;
diff --git a/test/Sema/expr-address-of.c b/test/Sema/expr-address-of.c
index 8f9f795d00..2b8cfbfa68 100644
--- a/test/Sema/expr-address-of.c
+++ b/test/Sema/expr-address-of.c
@@ -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}}
+}