]> granicus.if.org Git - clang/commitdiff
Diagnose binding a non-const reference to a vector element.
authorAnders Carlsson <andersca@mac.com>
Sun, 31 Jan 2010 17:18:49 +0000 (17:18 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 31 Jan 2010 17:18:49 +0000 (17:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94963 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/Expr.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaInit.cpp
test/SemaCXX/references.cpp

index 252781767169607cf49c84a0b3eb6107afda1740..7f3c5cde38937028dfb4446f9a68f796587ebfbc 100644 (file)
@@ -192,6 +192,9 @@ public:
     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
index 1f48cd75b1d63e8c901bb8a907806c5f9bd7a6a4..0d1a0e21024ebe50309e3a8ce3cd513058ff6b6e 100644 (file)
@@ -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<
index 66f06e090afdf5bd2845a560888e518dc58f62f7..b76048a2b8d144cddb704bfa3f00c0d80b6193db 100644 (file)
@@ -1977,6 +1977,25 @@ FieldDecl *Expr::getBitField() {
   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 {
index 3b09a583cd2a0a2b700d1e8c046481c26a52860f..75be50fc0fd9fa235eb049f5bdb76e33cb4bfa7d 100644 (file)
@@ -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<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();
index 5269167df2c17b21ae42ba462cdb2f0f5751134f..a9adb70050b78a8a17c7b796e82f70812600f571 100644 (file)
@@ -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
index 630f53f2839ececc915e97b8afc942d96777a68e..df8337bec82c270165c9dd85f0c301b0846dbf30 100644 (file)
@@ -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;
+}