forked from OSchip/llvm-project
Report accurate source-location information when rebuilding types during
template instantiation. llvm-svn: 85545
This commit is contained in:
parent
f3eb5ec2c0
commit
70dd5f6574
|
@ -775,6 +775,10 @@ public:
|
|||
getLocalData()->RBracketLoc = Loc;
|
||||
}
|
||||
|
||||
SourceRange getBracketsRange() const {
|
||||
return SourceRange(getLBracketLoc(), getRBracketLoc());
|
||||
}
|
||||
|
||||
Expr *getSizeExpr() const {
|
||||
return getLocalData()->Size;
|
||||
}
|
||||
|
|
|
@ -310,6 +310,8 @@ public:
|
|||
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 @@ public:
|
|||
///
|
||||
/// 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 @@ public:
|
|||
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 @@ public:
|
|||
/// 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 TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
|
|||
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 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
|
|||
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 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
|
|||
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 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
|
|||
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 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
|
|||
Result = getDerived().RebuildConstantArrayType(ElementType,
|
||||
T->getSizeModifier(),
|
||||
T->getSize(),
|
||||
T->getIndexTypeCVRQualifiers());
|
||||
T->getIndexTypeCVRQualifiers(),
|
||||
TL.getBracketsRange());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
@ -2290,7 +2306,8 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType(
|
|||
ElementType != T->getElementType()) {
|
||||
Result = getDerived().RebuildIncompleteArrayType(ElementType,
|
||||
T->getSizeModifier(),
|
||||
T->getIndexTypeCVRQualifiers());
|
||||
T->getIndexTypeCVRQualifiers(),
|
||||
TL.getBracketsRange());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
@ -2330,7 +2347,7 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
|
|||
T->getSizeModifier(),
|
||||
move(SizeResult),
|
||||
T->getIndexTypeCVRQualifiers(),
|
||||
T->getBracketsRange());
|
||||
TL.getBracketsRange());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
@ -2371,7 +2388,7 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
|
|||
T->getSizeModifier(),
|
||||
move(SizeResult),
|
||||
T->getIndexTypeCVRQualifiers(),
|
||||
T->getBracketsRange());
|
||||
TL.getBracketsRange());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
@ -4907,48 +4924,42 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
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 @@ QualType
|
|||
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>
|
||||
|
|
|
@ -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.
|
||||
|
Loading…
Reference in New Issue