Index: test/Sema/cxx-references.cpp =================================================================== --- test/Sema/cxx-references.cpp (revision 0) +++ test/Sema/cxx-references.cpp (revision 0) @@ -0,0 +1,15 @@ +// 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; +} Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h (revision 39794) +++ include/clang/AST/Expr.h (working copy) @@ -59,6 +59,7 @@ /// - e->name /// - *e, the type of e cannot be a function type /// - string-constant + /// - reference type [C++ 3.10p5] /// enum isLvalueResult { LV_Valid, @@ -66,7 +67,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 39794) +++ Sema/SemaExpr.cpp (working copy) @@ -291,7 +291,7 @@ // to the expression *((e1)+(e2)). This means the array "Base" may actually be // in the subscript position. As a result, we need to derive the array base // and index from the expression types. - + Expr *baseExpr, *indexExpr; QualType baseType, indexType; if (isa(canonT1) || isa(canonT1)) { @@ -304,6 +304,18 @@ indexType = canonT1; baseExpr = static_cast(Idx); indexExpr = static_cast(Base); + } else if (isa(canonT1)) { + // C++ 8.5.3p1: A reference to an array. + baseType = canonT1; + indexType = canonT2; + baseExpr = static_cast(Base); + indexExpr = static_cast(Idx); + } else if (isa(canonT2)) { // uncommon + // C++ 8.5.3p1: A reference to an array. + baseType = canonT2; + indexType = canonT1; + baseExpr = static_cast(Idx); + indexExpr = static_cast(Base); } else { return Diag(static_cast(Base)->getLocStart(), diag::err_typecheck_subscript_value, @@ -325,8 +337,11 @@ diag::err_typecheck_subscript_not_object, baseType.getAsString(), baseExpr->getSourceRange()); } - } else if (VectorType *vec = dyn_cast(baseType)) + } else if (VectorType *vec = dyn_cast(baseType)) { resultType = vec->getElementType(); + } else if (ReferenceType *ref = dyn_cast(baseType)) { + resultType = cast(ref->getReferenceeType())->getElementType(); + } return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType, RLoc); } @@ -382,16 +397,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)); Index: AST/Expr.cpp =================================================================== --- AST/Expr.cpp (revision 39794) +++ AST/Expr.cpp (working copy) @@ -190,15 +190,19 @@ /// - e->name /// - *e, the type of e cannot be a function type /// - string-constant +/// - reference type [C++ 3.10p5] /// -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++ 3.10p5 references + return LV_Valid; + // the type looks fine, now check the expression switch (getStmtClass()) { case StringLiteralClass: // C99 6.5.1p4