Index: test/Sema/cxx-references.cpp =================================================================== --- test/Sema/cxx-references.cpp (revision 0) +++ test/Sema/cxx-references.cpp (revision 0) @@ -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; +} Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h (revision 39900) +++ include/clang/AST/Expr.h (working copy) @@ -61,6 +61,7 @@ /// - e->name /// - *e, the type of e cannot be a function type /// - string-constant + /// - reference type [C++ 3.10p5] /// enum isLvalueResult { LV_Valid, @@ -68,7 +69,7 @@ LV_IncompleteVoidType, LV_InvalidExpression }; - isLvalueResult isLvalue(); + isLvalueResult isLvalue() const; /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, /// does not have an incomplete type, does not have a const-qualified type, Index: Sema/SemaExpr.cpp =================================================================== --- Sema/SemaExpr.cpp (revision 39900) +++ Sema/SemaExpr.cpp (working copy) @@ -282,10 +282,8 @@ Expr *LHSExp = static_cast(Base), *RHSExp = static_cast(Idx); // Perform default conversions. - DefaultFunctionArrayConversion(LHSExp); - DefaultFunctionArrayConversion(RHSExp); - - QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); + QualType LHSTy = DefaultFunctionArrayConversion(LHSExp); + QualType RHSTy = DefaultFunctionArrayConversion(RHSExp); assert(!LHSTy.isNull() && !RHSTy.isNull() && "missing types"); // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent @@ -381,16 +379,32 @@ // type pointer to function". const PointerType *PT = dyn_cast(qType); if (PT == 0) PT = dyn_cast(qType.getCanonicalType()); - - if (PT == 0) - return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function, - SourceRange(funcExpr->getLocStart(), RParenLoc)); - - const FunctionType *funcT = dyn_cast(PT->getPointeeType()); + + const FunctionType *funcT = 0; + + if (PT == 0) { + // C++ 8.5.3p1: This is a reference to a function. + const ReferenceType *RT = dyn_cast(qType); + + if (RT) { + funcT = dyn_cast(RT->getReferenceeType()); + + if (funcT == 0) + funcT = + dyn_cast(RT->getReferenceeType().getCanonicalType()); + } else { + return Diag(funcExpr->getLocStart(), + diag::err_typecheck_call_not_function, + SourceRange(funcExpr->getLocStart(), RParenLoc)); + } + } else { + funcT = dyn_cast(PT->getPointeeType()); + + if (funcT == 0) + funcT = dyn_cast(PT->getPointeeType().getCanonicalType()); + } + if (funcT == 0) - funcT = dyn_cast(PT->getPointeeType().getCanonicalType()); - - if (funcT == 0) return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function, SourceRange(funcExpr->getLocStart(), RParenLoc)); @@ -579,7 +593,9 @@ QualType Sema::DefaultFunctionArrayConversion(Expr *&e) { QualType t = e->getType(); assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type"); - + + if (const ReferenceType *ref = dyn_cast(t.getCanonicalType())) + t = ref->getReferenceeType(); // C++ 5p5 if (t->isFunctionType()) return promoteExprToType(e, Context.getPointerType(t)); if (const ArrayType *ary = dyn_cast(t.getCanonicalType())) @@ -596,6 +612,8 @@ QualType t = expr->getType(); assert(!t.isNull() && "UsualUnaryConversions - missing type"); + if (const ReferenceType *ref = dyn_cast(t.getCanonicalType())) + t = ref->getReferenceeType(); // C++ 5p5 if (t->isPromotableIntegerType()) // C99 6.3.1.1p2 return promoteExprToType(expr, Context.IntTy); return DefaultFunctionArrayConversion(expr); Index: AST/Expr.cpp =================================================================== --- AST/Expr.cpp (revision 39900) +++ AST/Expr.cpp (working copy) @@ -191,15 +191,19 @@ /// - e->name /// - *e, the type of e cannot be a function type /// - string-constant +/// - reference type [C++ 5p5] /// -Expr::isLvalueResult Expr::isLvalue() { +Expr::isLvalueResult Expr::isLvalue() const { // first, check the type (C99 6.3.2.1) if (isa(TR.getCanonicalType())) // from isObjectType() return LV_NotObjectType; if (TR->isIncompleteType() && TR->isVoidType()) return LV_IncompleteVoidType; - + + if (isa(TR.getCanonicalType())) // C++ 5p5 + return LV_Valid; + // the type looks fine, now check the expression switch (getStmtClass()) { case StringLiteralClass: // C99 6.5.1p4