]> granicus.if.org Git - clang/commitdiff
Fix references:
authorBill Wendling <isanbard@gmail.com>
Tue, 17 Jul 2007 03:52:31 +0000 (03:52 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 17 Jul 2007 03:52:31 +0000 (03:52 +0000)
    According to the spec (C++ 5p6[expr]), we need to adjust "T&" to
    "T" before further analysis. We do this via the "implicit cast"
    thingy.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39953 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Expr.cpp
Sema/SemaExpr.cpp
include/clang/AST/Expr.h
test/Sema/cxx-references.cpp [new file with mode: 0644]

index 2edea9796d4992f31b0b0dc1c341ef9b4a3e31a1..7b8e1fdf5ea6db4613833452a27759a0808eef79 100644 (file)
@@ -191,6 +191,7 @@ bool Expr::hasLocalSideEffect() const {
 ///  - e->name
 ///  - *e, the type of e cannot be a function type
 ///  - string-constant
+///  - reference type [C++ [expr]]
 ///
 Expr::isLvalueResult Expr::isLvalue() const {
   // first, check the type (C99 6.3.2.1)
@@ -199,7 +200,10 @@ Expr::isLvalueResult Expr::isLvalue() const {
 
   if (TR->isIncompleteType() && TR->isVoidType())
     return LV_IncompleteVoidType;
-    
+
+  if (isa<ReferenceType>(TR.getCanonicalType())) // C++ [expr]
+    return LV_Valid;
+
   // the type looks fine, now check the expression
   switch (getStmtClass()) {
   case StringLiteralClass: // C99 6.5.1p4
index f0d4ac2040e063ab9a339c4501f48076a567add0..93a2df90aa5c4cadd06c4643316f298a4e90d96d 100644 (file)
@@ -596,7 +596,9 @@ static void promoteExprToType(Expr *&expr, QualType type) {
 void Sema::DefaultFunctionArrayConversion(Expr *&e) {
   QualType t = e->getType();
   assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
-  
+
+  if (const ReferenceType *ref = dyn_cast<ReferenceType>(t.getCanonicalType()))
+    t = promoteExprToType(e, ref->getReferenceeType()); // C++ [expr]
   if (t->isFunctionType())
     promoteExprToType(e, Context.getPointerType(t));
   else if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
@@ -612,6 +614,8 @@ void Sema::UsualUnaryConversions(Expr *&expr) {
   QualType t = expr->getType();
   assert(!t.isNull() && "UsualUnaryConversions - missing type");
   
+  if (const ReferenceType *ref = dyn_cast<ReferenceType>(t.getCanonicalType()))
+    t = promoteExprToType(expr, ref->getReferenceeType()); // C++ [expr]
   if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
     promoteExprToType(expr, Context.IntTy);
   else
index 47c36bbd5b0cc0700c99dc5526e7c7a62154034c..baa787dec844a27fa2ff3cb8ed07b4e5e42434d8 100644 (file)
@@ -61,6 +61,7 @@ public:
   ///  - e->name
   ///  - *e, the type of e cannot be a function type
   ///  - string-constant
+  ///  - reference type [C++ [expr]]
   ///
   enum isLvalueResult {
     LV_Valid,
diff --git a/test/Sema/cxx-references.cpp b/test/Sema/cxx-references.cpp
new file mode 100644 (file)
index 0000000..785180d
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only %s
+int g(int);
+
+void f() {
+  int i;
+  int &r = i;
+  r = 1;
+  int *p = &r;
+  int &rr = r;
+  int (&rg)(int) = g;
+  rg(i);
+  int a[3];
+  int (&ra)[3] = a;
+  ra[1] = i;
+  int *Q;
+  int *& P = Q;
+  P[1] = 1;
+}