[cfe-commits] r85545 - in /cfe/trunk: include/clang/AST/TypeLoc.h lib/Sema/TreeTransform.h test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp
John McCall
rjmccall at apple.com
Thu Oct 29 17:06:24 PDT 2009
Author: rjmccall
Date: Thu Oct 29 19:06:24 2009
New Revision: 85545
URL: http://llvm.org/viewvc/llvm-project?rev=85545&view=rev
Log:
Report accurate source-location information when rebuilding types during
template instantiation.
Added:
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp
Modified:
cfe/trunk/include/clang/AST/TypeLoc.h
cfe/trunk/lib/Sema/TreeTransform.h
Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=85545&r1=85544&r2=85545&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Oct 29 19:06:24 2009
@@ -775,6 +775,10 @@
getLocalData()->RBracketLoc = Loc;
}
+ SourceRange getBracketsRange() const {
+ return SourceRange(getLBracketLoc(), getRBracketLoc());
+ }
+
Expr *getSizeExpr() const {
return getLocalData()->Size;
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=85545&r1=85544&r2=85545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Oct 29 19:06:24 2009
@@ -310,6 +310,8 @@
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+
QualType
TransformTemplateSpecializationType(const TemplateSpecializationType *T,
QualType ObjectType);
@@ -332,35 +334,37 @@
///
/// By default, performs semantic analysis when building the pointer type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildPointerType(QualType PointeeType);
+ QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
/// \brief Build a new block pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the block pointer
/// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildBlockPointerType(QualType PointeeType);
+ QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new lvalue reference type given the type it references.
+ /// \brief Build a new reference type given the type it references.
///
- /// By default, performs semantic analysis when building the lvalue reference
- /// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildLValueReferenceType(QualType ReferentType);
-
- /// \brief Build a new rvalue reference type given the type it references.
+ /// By default, performs semantic analysis when building the
+ /// reference type. Subclasses may override this routine to provide
+ /// different behavior.
///
- /// By default, performs semantic analysis when building the rvalue reference
- /// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildRValueReferenceType(QualType ReferentType);
+ /// \param LValue whether the type was written with an lvalue sigil
+ /// or an rvalue sigil.
+ QualType RebuildReferenceType(QualType ReferentType,
+ bool LValue,
+ SourceLocation Sigil);
/// \brief Build a new member pointer type given the pointee type and the
/// class type it refers into.
///
/// By default, performs semantic analysis when building the member pointer
/// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
+ QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+ SourceLocation Sigil);
/// \brief Build a new Objective C object pointer type.
- QualType RebuildObjCObjectPointerType(QualType PointeeType);
+ QualType RebuildObjCObjectPointerType(QualType PointeeType,
+ SourceLocation Sigil);
/// \brief Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
@@ -384,7 +388,8 @@
QualType RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
- unsigned IndexTypeQuals);
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
/// \brief Build a new incomplete array type given the element type, size
/// modifier, and index type qualifiers.
@@ -393,7 +398,8 @@
/// Subclasses may override this routine to provide different behavior.
QualType RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- unsigned IndexTypeQuals);
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
/// \brief Build a new variable-length array type given the element type,
/// size modifier, size expression, and index type qualifiers.
@@ -2124,7 +2130,8 @@
QualType Result = TL.getType(); \
if (getDerived().AlwaysRebuild() || \
PointeeType != TL.getPointeeLoc().getType()) { \
- Result = getDerived().Rebuild##TypeClass(PointeeType); \
+ Result = getDerived().Rebuild##TypeClass(PointeeType, \
+ TL.getSigilLoc()); \
if (Result.isNull()) \
return QualType(); \
} \
@@ -2135,35 +2142,6 @@
return Result; \
} while(0)
-// Reference collapsing forces us to transform reference types
-// differently from the other pointer-like types.
-#define TransformReferenceType(TypeClass) do { \
- QualType PointeeType \
- = getDerived().TransformType(TLB, TL.getPointeeLoc()); \
- if (PointeeType.isNull()) \
- return QualType(); \
- \
- QualType Result = TL.getType(); \
- if (getDerived().AlwaysRebuild() || \
- PointeeType != TL.getPointeeLoc().getType()) { \
- Result = getDerived().Rebuild##TypeClass(PointeeType); \
- if (Result.isNull()) \
- return QualType(); \
- } \
- \
- /* Workaround: rebuild doesn't always change the type */ \
- /* FIXME: avoid losing this location information. */ \
- if (Result == PointeeType) \
- return Result; \
- ReferenceTypeLoc NewTL; \
- if (isa<LValueReferenceType>(Result)) \
- NewTL = TLB.push<LValueReferenceTypeLoc>(Result); \
- else \
- NewTL = TLB.push<RValueReferenceTypeLoc>(Result); \
- NewTL.setSigilLoc(TL.getSigilLoc()); \
- return Result; \
-} while (0)
-
template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
BuiltinTypeLoc T) {
@@ -2197,18 +2175,54 @@
TransformPointerLikeType(BlockPointerType);
}
+/// Transforms a reference type. Note that somewhat paradoxically we
+/// don't care whether the type itself is an l-value type or an r-value
+/// type; we only care if the type was *written* as an l-value type
+/// or an r-value type.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
+ ReferenceTypeLoc TL) {
+ const ReferenceType *T = TL.getTypePtr();
+
+ // Note that this works with the pointee-as-written.
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeTypeAsWritten()) {
+ Result = getDerived().RebuildReferenceType(PointeeType,
+ T->isSpelledAsLValue(),
+ TL.getSigilLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // r-value references can be rebuilt as l-value references.
+ ReferenceTypeLoc NewTL;
+ if (isa<LValueReferenceType>(Result))
+ NewTL = TLB.push<LValueReferenceTypeLoc>(Result);
+ else
+ NewTL = TLB.push<RValueReferenceTypeLoc>(Result);
+ NewTL.setSigilLoc(TL.getSigilLoc());
+
+ return Result;
+}
+
template<typename Derived>
QualType
TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
LValueReferenceTypeLoc TL) {
- TransformReferenceType(LValueReferenceType);
+ return TransformReferenceType(TLB, TL);
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
RValueReferenceTypeLoc TL) {
- TransformReferenceType(RValueReferenceType);
+ return TransformReferenceType(TLB, TL);
}
template<typename Derived>
@@ -2231,7 +2245,8 @@
if (getDerived().AlwaysRebuild() ||
PointeeType != T->getPointeeType() ||
ClassType != QualType(T->getClass(), 0)) {
- Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+ Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType,
+ TL.getStarLoc());
if (Result.isNull())
return QualType();
}
@@ -2257,7 +2272,8 @@
Result = getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeCVRQualifiers());
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2290,7 +2306,8 @@
ElementType != T->getElementType()) {
Result = getDerived().RebuildIncompleteArrayType(ElementType,
T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers());
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2330,7 +2347,7 @@
T->getSizeModifier(),
move(SizeResult),
T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2371,7 +2388,7 @@
T->getSizeModifier(),
move(SizeResult),
T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -4907,48 +4924,42 @@
//===----------------------------------------------------------------------===//
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star,
getDerived().getBaseEntity());
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
- return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star,
getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
+TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
+ bool WrittenAsLValue,
+ SourceLocation Sigil) {
+ return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(),
+ Sigil, getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
-}
-
-template<typename Derived>
-QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
- QualType ClassType) {
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+ QualType ClassType,
+ SourceLocation Sigil) {
return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
+ Sigil, getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType,
+ SourceLocation Sigil) {
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Sigil,
getDerived().getBaseEntity());
}
@@ -4992,18 +5003,20 @@
TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
- unsigned IndexTypeQuals) {
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
- IndexTypeQuals, SourceRange());
+ IndexTypeQuals, BracketsRange);
}
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- unsigned IndexTypeQuals) {
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
- IndexTypeQuals, SourceRange());
+ IndexTypeQuals, BracketsRange);
}
template<typename Derived>
Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp?rev=85545&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp Thu Oct 29 19:06:24 2009
@@ -0,0 +1,145 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++ [dcl.ref]p5:
+// There shall be no references to references, no arrays of
+// references, and no pointers to references.
+
+// The crazy formatting in here is to enforce the exact report locations.
+
+typedef int &intref;
+typedef intref &intrefref;
+
+template <class T> class RefMem {
+ T
+ &
+ member;
+};
+
+struct RefRef {
+ int
+ &
+ & // expected-error {{declared as a reference to a reference}}
+ refref0;
+
+ intref
+ &
+ refref1; // collapses
+
+ intrefref
+ &
+ refref2; // collapses
+
+ RefMem
+ <
+ int
+ &
+ >
+ refref3; // collapses
+};
+
+
+template <class T> class PtrMem {
+ T
+ * // expected-error {{declared as a pointer to a reference}}
+ member;
+};
+
+struct RefPtr {
+ typedef
+ int
+ &
+ * // expected-error {{declared as a pointer to a reference}}
+ intrefptr;
+
+ typedef
+ intref
+ * // expected-error {{declared as a pointer to a reference}}
+ intrefptr2;
+
+ int
+ &
+ * // expected-error {{declared as a pointer to a reference}}
+ refptr0;
+
+ intref
+ * // expected-error {{declared as a pointer to a reference}}
+ refptr1;
+
+ PtrMem
+ <
+ int
+ &
+ >
+ refptr2; // expected-note {{in instantiation}}
+};
+
+template <class T> class ArrMem {
+ T
+ member
+ [ // expected-error {{declared as array of references}}
+ 10
+ ];
+};
+template <class T, unsigned N> class DepArrMem {
+ T
+ member
+ [ // expected-error {{declared as array of references}}
+ N
+ ];
+};
+
+struct RefArr {
+ typedef
+ int
+ &
+ intrefarr
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+
+ typedef
+ intref
+ intrefarr
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+
+ int
+ &
+ refarr0
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+ intref
+ refarr1
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+ ArrMem
+ <
+ int
+ &
+ >
+ refarr2; // expected-note {{in instantiation}}
+ DepArrMem
+ <
+ int
+ &,
+ 10
+ >
+ refarr3; // expected-note {{in instantiation}}
+};
+
+
+// The declaration of a reference shall contain an initializer
+// (8.5.3) except when the declaration contains an explicit extern
+// specifier (7.1.1), is a class member (9.2) declaration within a
+// class definition, or is the declaration of a parameter or a
+// return type (8.3.5); see 3.1. A reference shall be initialized to
+// refer to a valid object or function. [ Note: in particular, a
+// null reference cannot exist in a well-defined program, because
+// the only way to create such a reference would be to bind it to
+// the "object" obtained by dereferencing a null pointer, which
+// causes undefined behavior. As described in 9.6, a reference
+// cannot be bound directly to a bit-field.
+
More information about the cfe-commits
mailing list