diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-11-03 15:51:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-11-03 15:51:28 +0000 |
commit | f1f9b4e5c7fd087e78f2e387c01098d49d41e784 (patch) | |
tree | 2b284ad30db30e9d23e65a1142666598ef13751e /lib/Sema/SemaType.cpp | |
parent | b4e66d5259f90e9aae4d40fc5de801e046c7df94 (diff) |
Implement C++ DR 106 and C++ DR 540, both of which deal with
reference-collapsing.
Implement diagnostic for formation of a reference to cv void.
Drop cv-qualifiers added to a reference type when the reference type
comes from a typedef.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58612 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 93f182c27e..85c57f53ad 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -232,6 +232,17 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) { Result.getAsString(), DS.getSourceRange()); } + // C++ [dcl.ref]p1: + // Cv-qualified references are ill-formed except when the + // cv-qualifiers are introduced through the use of a typedef + // (7.1.3) or of a template type argument (14.3), in which + // case the cv-qualifiers are ignored. + if (DS.getTypeSpecType() == DeclSpec::TST_typedef && + TypeQuals && Result->isReferenceType()) { + TypeQuals &= ~QualType::Const; + TypeQuals &= ~QualType::Volatile; + } + Result = Result.getQualifiedType(TypeQuals); } return Result; @@ -283,13 +294,33 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { // Apply the pointer typequals to the pointer object. T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals); break; - case DeclaratorChunk::Reference: - if (const ReferenceType *RT = T->getAsReferenceType()) { - // C++ 8.3.2p4: There shall be no references to references. - Diag(DeclType.Loc, diag::err_illegal_decl_reference_to_reference, - D.getIdentifier() ? D.getIdentifier()->getName() : "type name"); + case DeclaratorChunk::Reference: { + // Whether we should suppress the creation of the reference. + bool SuppressReference = false; + if (T->isReferenceType()) { + // C++ [dcl.ref]p4: There shall be no references to references. + // + // According to C++ DR 106, references to references are only + // diagnosed when they are written directly (e.g., "int & &"), + // but not when they happen via a typedef: + // + // typedef int& intref; + // typedef intref& intref2; + // + // Parser::ParserDeclaratorInternal 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. + SuppressReference = true; + } + + // C++ [dcl.ref]p1: + // A declarator that specifies the type “reference to cv void” + // is ill-formed. + if (T->isVoidType()) { + Diag(DeclType.Loc, diag::err_reference_to_void); D.setInvalidType(true); - T = RT->getPointeeType(); + T = Context.IntTy; } // Enforce C99 6.7.3p2: "Types other than pointer types derived from @@ -302,12 +333,14 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { DeclType.Ref.HasRestrict = false; } - T = Context.getReferenceType(T); + if (!SuppressReference) + T = Context.getReferenceType(T); // Handle restrict on references. if (DeclType.Ref.HasRestrict) T.addRestrict(); break; + } case DeclaratorChunk::Array: { DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr; Expr *ArraySize = static_cast<Expr*>(ATI.NumElts); |