From 8abde4b447dba9647a50b04e732294e2e2a4e843 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 31 Jan 2010 17:18:49 +0000 Subject: [PATCH] Diagnose binding a non-const reference to a vector element. llvm-svn: 94963 --- clang/include/clang/AST/Expr.h | 3 +++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/AST/Expr.cpp | 19 +++++++++++++++++++ clang/lib/Sema/SemaExpr.cpp | 3 +-- clang/lib/Sema/SemaInit.cpp | 10 +++++++++- clang/test/SemaCXX/references.cpp | 13 +++++++++++++ 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 252781767169..7f3c5cde3893 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -192,6 +192,9 @@ public: return const_cast(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 diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1f48cd75b1d6..0d1a0e21024e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -584,6 +584,8 @@ def err_reference_init_drops_quals : Error< "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< diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 66f06e090afd..b76048a2b8d1 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1977,6 +1977,25 @@ FieldDecl *Expr::getBitField() { return 0; } +bool Expr::refersToVectorElement() const { + const Expr *E = this->IgnoreParens(); + + while (const ImplicitCastExpr *ICE = dyn_cast(E)) { + if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp) + E = ICE->getSubExpr()->IgnoreParens(); + else + break; + } + + if (const ArraySubscriptExpr *ASE = dyn_cast(E)) + return ASE->getBase()->getType()->isVectorType(); + + if (isa(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 { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 3b09a583cd2a..75be50fc0fd9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5968,8 +5968,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { Diag(OpLoc, diag::err_typecheck_address_of) << "bit-field" << op->getSourceRange(); return QualType(); - } else if (isa(op) || (isa(op) && - cast(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(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5269167df2c1..a9adb70050b7 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2341,7 +2341,7 @@ static void TryReferenceInitialization(Sema &S, 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; } @@ -3284,6 +3284,14 @@ InitializationSequence::Perform(Sema &S, 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 diff --git a/clang/test/SemaCXX/references.cpp b/clang/test/SemaCXX/references.cpp index 630f53f2839e..df8337bec82c 100644 --- a/clang/test/SemaCXX/references.cpp +++ b/clang/test/SemaCXX/references.cpp @@ -102,3 +102,16 @@ string getInput(); 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; +}