diff options
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 16 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp | 38 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp | 26 |
6 files changed, 78 insertions, 11 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index bd128f0514..9870b515c6 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -103,6 +103,9 @@ break; \ } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), ShouldAKA)); + } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) { + QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); } return QC.apply(Context, QT); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index bec201ce23..523054b2d8 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -506,6 +506,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, return TPResult::Error(); if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || + Tok.is(tok::ampamp) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { // ptr-operator ConsumeToken(); @@ -608,6 +609,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::l_square: case tok::l_paren: case tok::amp: + case tok::ampamp: case tok::star: case tok::plus: case tok::plusplus: diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 9130603d56..9593489b80 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2575,9 +2575,7 @@ static void TryReferenceInitialization(Sema &S, // - Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference - // shall be an rvalue reference and the initializer expression shall - // be an rvalue or have a function type. - // We handled the function type stuff above. + // shall be an rvalue reference. if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) || (isRValueRef && InitCategory.isRValue()))) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9a75d3604d..40d3734836 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1001,14 +1001,14 @@ QualType Sema::BuildPointerType(QualType T, QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, SourceLocation Loc, DeclarationName Entity) { + // C++0x [dcl.ref]p6: + // If a typedef (7.1.3), a type template-parameter (14.3.1), or a + // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a + // type T, an attempt to create the type "lvalue reference to cv TR" creates + // the type "lvalue reference to T", while an attempt to create the type + // "rvalue reference to cv TR" creates the type TR. bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>(); - // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a - // reference to a type T, and attempt to create the type "lvalue - // reference to cv TD" creates the type "lvalue reference to T". - // We use the qualifiers (restrict or none) of the original reference, - // not the new ones. This is consistent with GCC. - // C++ [dcl.ref]p4: There shall be no references to references. // // According to C++ DR 106, references to references are only @@ -1020,8 +1020,8 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, // // Parser::ParseDeclaratorInternal diagnoses the case where // references are written directly; here, we handle the - // collapsing of references-to-references as described in C++ - // DR 106 and amended by C++ DR 540. + // collapsing of references-to-references as described in C++0x. + // DR 106 and 540 introduce reference-collapsing into C++98/03. // C++ [dcl.ref]p1: // A declarator that specifies the type "reference to cv void" diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp new file mode 100644 index 0000000000..ef230509b2 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Test the C++0x-specific reference initialization rules, e.g., the +// rules for rvalue references. +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +struct Base { }; +struct Derived : Base { }; + +struct HasArray { + int array[5]; +}; + +int f(int); + +void test_rvalue_refs() { + // If the initializer expression... + + // - is an xvalue, class prvalue, array prvalue or function lvalue + // and "cv1 T1" is reference-compatible with "cv2 T2", or + + // xvalue case + Base&& base0 = xvalue<Base>(); + Base&& base1 = xvalue<Derived>(); + int&& int0 = xvalue<int>(); + + // class prvalue case + Base&& base2 = prvalue<Base>(); + Base&& base3 = prvalue<Derived>(); + + // FIXME: array prvalue case + // int (&&array0)[5] = HasArray().array; + + // function lvalue case + int (&&function0)(int) = f; +} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp new file mode 100644 index 0000000000..789cde7524 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; +#define JOIN2(X,Y) X##Y +#define JOIN(X,Y) JOIN2(X,Y) +#define CHECK_EQUAL_TYPES(T1, T2) \ + int JOIN(array,__LINE__)[is_same<T1, T2>::value? 1 : -1] + +int i; +typedef int& LRI; +typedef int&& RRI; + +typedef LRI& r1; CHECK_EQUAL_TYPES(r1, int&); +typedef const LRI& r2; CHECK_EQUAL_TYPES(r2, int&); +typedef const LRI&& r3; CHECK_EQUAL_TYPES(r3, int&); + +typedef RRI& r4; CHECK_EQUAL_TYPES(r4, int&); +typedef RRI&& r5; CHECK_EQUAL_TYPES(r5, int&&); |