return const_cast<Expr*>(this)->getBitField();
}
+ /// \brief Returns whether this expression refers to a vector element.
+ bool refersToVectorElement() const;
+
/// isIntegerConstantExpr - Return true if this expression is a valid integer
/// constant expression, and, if so, return its value in Result. If not a
/// valid i-c-e, return false and fill in Loc (if specified) with the location
"qualifiers">;
def err_reference_bind_to_bitfield : Error<
"%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
+def err_reference_bind_to_vector_element : Error<
+ "%select{non-const|volatile}0 reference cannot bind to vector element">;
def err_reference_var_requires_init : Error<
"declaration of reference variable %0 requires an initializer">;
def err_const_var_requires_init : Error<
return 0;
}
+bool Expr::refersToVectorElement() const {
+ const Expr *E = this->IgnoreParens();
+
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ E = ICE->getSubExpr()->IgnoreParens();
+ else
+ break;
+ }
+
+ if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E))
+ return ASE->getBase()->getType()->isVectorType();
+
+ if (isa<ExtVectorElementExpr>(E))
+ return true;
+
+ return false;
+}
+
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool ExtVectorElementExpr::isArrow() const {
Diag(OpLoc, diag::err_typecheck_address_of)
<< "bit-field" << op->getSourceRange();
return QualType();
- } else if (isa<ExtVectorElementExpr>(op) || (isa<ArraySubscriptExpr>(op) &&
- cast<ArraySubscriptExpr>(op)->getBase()->getType()->isVectorType())){
+ } else if (op->refersToVectorElement()) {
// The operand cannot be an element of a vector
Diag(OpLoc, diag::err_typecheck_address_of)
<< "vector element" << op->getSourceRange();
if (T1Quals != T2Quals)
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
- Initializer->getBitField();
+ (Initializer->getBitField() || Initializer->refersToVectorElement());
Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
return;
}
return S.ExprError();
}
+ if (CurInitExpr->refersToVectorElement()) {
+ // Vector elements cannot bind to bit fields.
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+ << Entity.getType().isVolatileQualified()
+ << CurInitExpr->getSourceRange();
+ return S.ExprError();
+ }
+
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
void test9() {
string &s = getInput(); // expected-error{{lvalue reference}}
}
+
+void test10() {
+ __attribute((vector_size(16))) typedef int vec4;
+ typedef __attribute__(( ext_vector_type(4) )) int ext_vec4;
+
+ vec4 v;
+ int &a = v[0]; // expected-error{{non-const reference cannot bind to vector element}}
+ const int &b = v[0];
+
+ ext_vec4 ev;
+ int &c = ev.x; // expected-error{{non-const reference cannot bind to vector element}}
+ const int &d = ev.x;
+}