Update clang to 84175.
This commit is contained in:
parent
4c8b24812d
commit
98781354c3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=198112 svn path=/vendor/clang/clang-84175/; revision=198129; tag=vendor/clang/clang-r84175
@ -174,7 +174,7 @@ class ASTContext {
|
||||
/// This mapping will contain an entry that maps from the VarDecl for
|
||||
/// X<int>::value to the corresponding VarDecl for X<T>::value (within the
|
||||
/// class template X) and will be marked TSK_ImplicitInstantiation.
|
||||
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>
|
||||
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
|
||||
InstantiatedFromStaticDataMember;
|
||||
|
||||
/// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
|
||||
@ -267,7 +267,8 @@ class ASTContext {
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
/// class template specialization, returns the templated static data member
|
||||
/// from which it was instantiated.
|
||||
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(VarDecl *Var);
|
||||
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
|
||||
const VarDecl *Var);
|
||||
|
||||
/// \brief Note that the static data member \p Inst is an instantiation of
|
||||
/// the static data member template \p Tmpl of a class template.
|
||||
|
@ -584,19 +584,23 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
return getDeclContext()->isRecord();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a static data member.
|
||||
bool isOutOfLine() const;
|
||||
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
/// class template specialization, returns the templated static data member
|
||||
/// from which it was instantiated.
|
||||
VarDecl *getInstantiatedFromStaticDataMember();
|
||||
VarDecl *getInstantiatedFromStaticDataMember() const;
|
||||
|
||||
/// \brief If this variable is a static data member, determine what kind of
|
||||
/// template specialization or instantiation this is.
|
||||
TemplateSpecializationKind getTemplateSpecializationKind();
|
||||
TemplateSpecializationKind getTemplateSpecializationKind() const;
|
||||
|
||||
/// \brief If this variable is an instantiation of a static data member of a
|
||||
/// class template specialization, retrieves the member specialization
|
||||
/// information.
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo();
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo() const;
|
||||
|
||||
/// \brief For a static data member that was instantiated from a static
|
||||
/// data member of a class template, set the template specialiation kind.
|
||||
|
@ -20,6 +20,7 @@ namespace clang {
|
||||
class ParmVarDecl;
|
||||
class TypeSpecLoc;
|
||||
class DeclaratorInfo;
|
||||
class UnqualTypeLoc;
|
||||
|
||||
/// \brief Base wrapper for a particular "section" of type source info.
|
||||
///
|
||||
@ -27,22 +28,31 @@ namespace clang {
|
||||
/// get at the actual information.
|
||||
class TypeLoc {
|
||||
protected:
|
||||
QualType Ty;
|
||||
// The correctness of this relies on the property that, for Type *Ty,
|
||||
// QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
|
||||
void *Ty;
|
||||
void *Data;
|
||||
|
||||
public:
|
||||
TypeLoc() : Data(0) { }
|
||||
TypeLoc(QualType ty, void *opaqueData) : Ty(ty), Data(opaqueData) { }
|
||||
TypeLoc() : Ty(0), Data(0) { }
|
||||
TypeLoc(QualType ty, void *opaqueData)
|
||||
: Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
|
||||
TypeLoc(Type *ty, void *opaqueData)
|
||||
: Ty(ty), Data(opaqueData) { }
|
||||
|
||||
bool isNull() const { return Ty.isNull(); }
|
||||
operator bool() const { return !isNull(); }
|
||||
bool isNull() const { return !Ty; }
|
||||
operator bool() const { return Ty; }
|
||||
|
||||
/// \brief Returns the size of type source info data block for the given type.
|
||||
static unsigned getFullDataSizeForType(QualType Ty);
|
||||
|
||||
/// \brief Get the type for which this source info wrapper provides
|
||||
/// information.
|
||||
QualType getSourceType() const { return Ty; }
|
||||
QualType getSourceType() const { return QualType::getFromOpaquePtr(Ty); }
|
||||
|
||||
Type *getSourceTypePtr() const {
|
||||
return QualType::getFromOpaquePtr(Ty).getTypePtr();
|
||||
}
|
||||
|
||||
/// \brief Get the pointer where source information is stored.
|
||||
void *getOpaqueData() const { return Data; }
|
||||
@ -57,12 +67,17 @@ class TypeLoc {
|
||||
SourceRange getTypeSpecRange() const;
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const;
|
||||
unsigned getFullDataSize() const {
|
||||
return getFullDataSizeForType(getSourceType());
|
||||
}
|
||||
|
||||
/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
|
||||
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
|
||||
TypeLoc getNextTypeLoc() const;
|
||||
|
||||
/// \brief Skips past any qualifiers, if this is qualified.
|
||||
UnqualTypeLoc getUnqualifiedLoc() const;
|
||||
|
||||
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
|
||||
return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
|
||||
}
|
||||
@ -74,144 +89,300 @@ class TypeLoc {
|
||||
static bool classof(const TypeLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Base wrapper of type source info data for type-spec types.
|
||||
class TypeSpecLoc : public TypeLoc {
|
||||
/// \brief Wrapper of type source information for a type with
|
||||
/// no direct quqlaifiers.
|
||||
class UnqualTypeLoc : public TypeLoc {
|
||||
public:
|
||||
static bool classof(const TypeLoc *TL);
|
||||
UnqualTypeLoc() {}
|
||||
UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
|
||||
|
||||
Type *getSourceTypePtr() const {
|
||||
return reinterpret_cast<Type*>(Ty);
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return !TL->getSourceType().hasQualifiers();
|
||||
}
|
||||
static bool classof(const UnqualTypeLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Wrapper of type source information for a type with
|
||||
/// non-trivial direct qualifiers.
|
||||
///
|
||||
/// Currently, we intentionally do not provide source location for
|
||||
/// type qualifiers.
|
||||
class QualifiedLoc : public TypeLoc {
|
||||
public:
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
UnqualTypeLoc getUnqualifiedLoc() const {
|
||||
return UnqualTypeLoc(getSourceTypePtr(), Data);
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const {
|
||||
// In fact, we don't currently preserve any location information
|
||||
// for qualifiers.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() +
|
||||
getFullDataSizeForType(getSourceType().getUnqualifiedType());
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return TL->getSourceType().hasQualifiers();
|
||||
}
|
||||
static bool classof(const QualifiedLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
|
||||
if (isa<QualifiedLoc>(this))
|
||||
return cast<QualifiedLoc>(this)->getUnqualifiedLoc();
|
||||
return cast<UnqualTypeLoc>(*this);
|
||||
}
|
||||
|
||||
/// \brief Base wrapper of type source info data for type-spec types.
|
||||
class TypeSpecLoc : public UnqualTypeLoc {
|
||||
public:
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return (UnqualTypeLoc::classof(TL) &&
|
||||
classof(static_cast<const UnqualTypeLoc*>(TL)));
|
||||
}
|
||||
static bool classof(const UnqualTypeLoc *TL);
|
||||
static bool classof(const TypeSpecLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
inline SourceRange TypeLoc::getTypeSpecRange() const {
|
||||
return getTypeSpecLoc().getSourceRange();
|
||||
}
|
||||
|
||||
/// \brief Base wrapper of type source info data for types part of a declarator,
|
||||
/// excluding type-spec types.
|
||||
class DeclaratorLoc : public TypeLoc {
|
||||
class DeclaratorLoc : public UnqualTypeLoc {
|
||||
public:
|
||||
/// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc.
|
||||
TypeSpecLoc getTypeSpecLoc() const;
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return (UnqualTypeLoc::classof(TL) &&
|
||||
classof(static_cast<const UnqualTypeLoc*>(TL)));
|
||||
}
|
||||
static bool classof(const UnqualTypeLoc *TL);
|
||||
static bool classof(const DeclaratorLoc *TL) { return true; }
|
||||
};
|
||||
|
||||
|
||||
/// A metaprogramming base class for TypeLoc classes which correspond
|
||||
/// to a particular Type subclass. It is accepted for a single
|
||||
/// TypeLoc class to correspond to multiple Type classes.
|
||||
///
|
||||
/// \param Base a class from which to derive
|
||||
/// \param Derived the class deriving from this one
|
||||
/// \param TypeClass the concrete Type subclass associated with this
|
||||
/// location type
|
||||
/// \param LocalData the structure type of local location data for
|
||||
/// this type
|
||||
///
|
||||
/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
|
||||
/// else the world will end.
|
||||
///
|
||||
/// TypeLocs with non-constant amounts of local data should override
|
||||
/// getExtraLocalDataSize(); getExtraLocalData() will then point to
|
||||
/// this extra memory.
|
||||
///
|
||||
/// TypeLocs with an inner type should override hasInnerType() and
|
||||
/// getInnerType(); getInnerTypeLoc() will then point to this inner
|
||||
/// type's location data.
|
||||
template <class Base, class Derived, class TypeClass, class LocalData>
|
||||
class ConcreteTypeLoc : public Base {
|
||||
|
||||
const Derived *asDerived() const {
|
||||
return static_cast<const Derived*>(this);
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned getLocalDataSize() const {
|
||||
return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
|
||||
}
|
||||
// Give a default implementation that's useful for leaf types.
|
||||
unsigned getFullDataSize() const {
|
||||
return asDerived()->getLocalDataSize() + getInnerTypeSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return Derived::classofType(TL->getSourceTypePtr());
|
||||
}
|
||||
static bool classof(const UnqualTypeLoc *TL) {
|
||||
return Derived::classofType(TL->getSourceTypePtr());
|
||||
}
|
||||
static bool classof(const Derived *TL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool classofType(const Type *Ty) {
|
||||
return TypeClass::classof(Ty);
|
||||
}
|
||||
|
||||
protected:
|
||||
TypeClass *getTypePtr() const {
|
||||
return cast<TypeClass>(Base::getSourceTypePtr());
|
||||
}
|
||||
|
||||
unsigned getExtraLocalDataSize() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LocalData *getLocalData() const {
|
||||
return static_cast<LocalData*>(Base::Data);
|
||||
}
|
||||
|
||||
/// Gets a pointer past the Info structure; useful for classes with
|
||||
/// local data that can't be captured in the Info (e.g. because it's
|
||||
/// of variable size).
|
||||
void *getExtraLocalData() const {
|
||||
return getLocalData() + 1;
|
||||
}
|
||||
|
||||
void *getNonLocalData() const {
|
||||
return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
|
||||
}
|
||||
|
||||
bool hasInnerType() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeLoc getInnerTypeLoc() const {
|
||||
assert(asDerived()->hasInnerType());
|
||||
return TypeLoc(asDerived()->getInnerType(), getNonLocalData());
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned getInnerTypeSize() const {
|
||||
if (asDerived()->hasInnerType())
|
||||
return getInnerTypeLoc().getFullDataSize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Required here because my metaprogramming is too weak to avoid it.
|
||||
QualType getInnerType() const {
|
||||
assert(0 && "getInnerType() not overridden");
|
||||
return QualType();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct DefaultTypeSpecLocInfo {
|
||||
SourceLocation StartLoc;
|
||||
};
|
||||
|
||||
/// \brief The default wrapper for type-spec types that are not handled by
|
||||
/// another specific wrapper.
|
||||
class DefaultTypeSpecLoc : public TypeSpecLoc {
|
||||
struct Info {
|
||||
SourceLocation StartLoc;
|
||||
};
|
||||
|
||||
class DefaultTypeSpecLoc : public ConcreteTypeLoc<TypeSpecLoc,
|
||||
DefaultTypeSpecLoc,
|
||||
Type,
|
||||
DefaultTypeSpecLocInfo> {
|
||||
public:
|
||||
SourceLocation getStartLoc() const {
|
||||
return static_cast<Info*>(Data)->StartLoc;
|
||||
return getLocalData()->StartLoc;
|
||||
}
|
||||
void setStartLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->StartLoc = Loc;
|
||||
getLocalData()->StartLoc = Loc;
|
||||
}
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getStartLoc(), getStartLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
static bool classofType(const Type *T);
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const { return getLocalDataSize(); }
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const DefaultTypeSpecLoc *TL) { return true; }
|
||||
struct TypedefLocInfo {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for typedefs.
|
||||
class TypedefLoc : public TypeSpecLoc {
|
||||
struct Info {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
class TypedefLoc : public ConcreteTypeLoc<TypeSpecLoc,TypedefLoc,
|
||||
TypedefType,TypedefLocInfo> {
|
||||
public:
|
||||
SourceLocation getNameLoc() const {
|
||||
return static_cast<Info*>(Data)->NameLoc;
|
||||
return getLocalData()->NameLoc;
|
||||
}
|
||||
void setNameLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->NameLoc = Loc;
|
||||
getLocalData()->NameLoc = Loc;
|
||||
}
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getNameLoc(), getNameLoc());
|
||||
}
|
||||
|
||||
TypedefDecl *getTypedefDecl() const {
|
||||
return cast<TypedefType>(Ty)->getDecl();
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const { return getLocalDataSize(); }
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const TypedefLoc *TL) { return true; }
|
||||
struct ObjCInterfaceLocInfo {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for ObjC interfaces.
|
||||
class ObjCInterfaceLoc : public TypeSpecLoc {
|
||||
struct Info {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
class ObjCInterfaceLoc : public ConcreteTypeLoc<TypeSpecLoc,
|
||||
ObjCInterfaceLoc,
|
||||
ObjCInterfaceType,
|
||||
ObjCInterfaceLocInfo> {
|
||||
public:
|
||||
SourceLocation getNameLoc() const {
|
||||
return static_cast<Info*>(Data)->NameLoc;
|
||||
return getLocalData()->NameLoc;
|
||||
}
|
||||
void setNameLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->NameLoc = Loc;
|
||||
getLocalData()->NameLoc = Loc;
|
||||
}
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getNameLoc(), getNameLoc());
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl *getIFaceDecl() const {
|
||||
return cast<ObjCInterfaceType>(Ty)->getDecl();
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const { return getLocalDataSize(); }
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const TypedefLoc *TL) { return true; }
|
||||
struct ObjCProtocolListLocInfo {
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for ObjC protocol lists.
|
||||
class ObjCProtocolListLoc : public TypeSpecLoc {
|
||||
struct Info {
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
};
|
||||
class ObjCProtocolListLoc : public ConcreteTypeLoc<TypeSpecLoc,
|
||||
ObjCProtocolListLoc,
|
||||
ObjCProtocolListType,
|
||||
ObjCProtocolListLocInfo> {
|
||||
// SourceLocations are stored after Info, one for each Protocol.
|
||||
SourceLocation *getProtocolLocArray() const {
|
||||
return reinterpret_cast<SourceLocation*>(static_cast<Info*>(Data) + 1);
|
||||
return (SourceLocation*) getExtraLocalData();
|
||||
}
|
||||
|
||||
public:
|
||||
SourceLocation getLAngleLoc() const {
|
||||
return static_cast<Info*>(Data)->LAngleLoc;
|
||||
return getLocalData()->LAngleLoc;
|
||||
}
|
||||
void setLAngleLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->LAngleLoc = Loc;
|
||||
getLocalData()->LAngleLoc = Loc;
|
||||
}
|
||||
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return static_cast<Info*>(Data)->RAngleLoc;
|
||||
return getLocalData()->RAngleLoc;
|
||||
}
|
||||
void setRAngleLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->RAngleLoc = Loc;
|
||||
getLocalData()->RAngleLoc = Loc;
|
||||
}
|
||||
|
||||
unsigned getNumProtocols() const {
|
||||
return cast<ObjCProtocolListType>(Ty)->getNumProtocols();
|
||||
return getTypePtr()->getNumProtocols();
|
||||
}
|
||||
|
||||
SourceLocation getProtocolLoc(unsigned i) const {
|
||||
@ -225,12 +396,11 @@ class ObjCProtocolListLoc : public TypeSpecLoc {
|
||||
|
||||
ObjCProtocolDecl *getProtocol(unsigned i) const {
|
||||
assert(i < getNumProtocols() && "Index is out of bounds!");
|
||||
return *(cast<ObjCProtocolListType>(Ty)->qual_begin() + i);
|
||||
return *(getTypePtr()->qual_begin() + i);
|
||||
}
|
||||
|
||||
TypeLoc getBaseTypeLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<ObjCProtocolListType>(Ty)->getBaseType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
@ -239,36 +409,34 @@ class ObjCProtocolListLoc : public TypeSpecLoc {
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const {
|
||||
return sizeof(Info) + getNumProtocols() * sizeof(SourceLocation);
|
||||
unsigned getExtraLocalDataSize() const {
|
||||
return getNumProtocols() * sizeof(SourceLocation);
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getBaseTypeLoc().getFullDataSize();
|
||||
}
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getBaseType(); }
|
||||
};
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const ObjCProtocolListLoc *TL) { return true; }
|
||||
|
||||
struct PointerLocInfo {
|
||||
SourceLocation StarLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for pointers.
|
||||
class PointerLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation StarLoc;
|
||||
};
|
||||
|
||||
class PointerLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
PointerLoc,
|
||||
PointerType,
|
||||
PointerLocInfo> {
|
||||
public:
|
||||
SourceLocation getStarLoc() const {
|
||||
return static_cast<Info*>(Data)->StarLoc;
|
||||
return getLocalData()->StarLoc;
|
||||
}
|
||||
void setStarLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->StarLoc = Loc;
|
||||
getLocalData()->StarLoc = Loc;
|
||||
}
|
||||
|
||||
TypeLoc getPointeeLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<PointerType>(Ty)->getPointeeType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this PointerLoc.
|
||||
@ -280,36 +448,30 @@ class PointerLoc : public DeclaratorLoc {
|
||||
return SourceRange(getStarLoc(), getStarLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getPointeeType(); }
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getPointeeLoc().getFullDataSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const PointerLoc *TL) { return true; }
|
||||
struct BlockPointerLocInfo {
|
||||
SourceLocation CaretLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for block pointers.
|
||||
class BlockPointerLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation CaretLoc;
|
||||
};
|
||||
|
||||
class BlockPointerLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
BlockPointerLoc,
|
||||
BlockPointerType,
|
||||
BlockPointerLocInfo> {
|
||||
public:
|
||||
SourceLocation getCaretLoc() const {
|
||||
return static_cast<Info*>(Data)->CaretLoc;
|
||||
return getLocalData()->CaretLoc;
|
||||
}
|
||||
void setCaretLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->CaretLoc = Loc;
|
||||
getLocalData()->CaretLoc = Loc;
|
||||
}
|
||||
|
||||
TypeLoc getPointeeLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<BlockPointerType>(Ty)->getPointeeType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this BlockPointerLoc.
|
||||
@ -321,36 +483,30 @@ class BlockPointerLoc : public DeclaratorLoc {
|
||||
return SourceRange(getCaretLoc(), getCaretLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getPointeeType(); }
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getPointeeLoc().getFullDataSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const BlockPointerLoc *TL) { return true; }
|
||||
struct MemberPointerLocInfo {
|
||||
SourceLocation StarLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for member pointers.
|
||||
class MemberPointerLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation StarLoc;
|
||||
};
|
||||
|
||||
class MemberPointerLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
MemberPointerLoc,
|
||||
MemberPointerType,
|
||||
MemberPointerLocInfo> {
|
||||
public:
|
||||
SourceLocation getStarLoc() const {
|
||||
return static_cast<Info*>(Data)->StarLoc;
|
||||
return getLocalData()->StarLoc;
|
||||
}
|
||||
void setStarLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->StarLoc = Loc;
|
||||
getLocalData()->StarLoc = Loc;
|
||||
}
|
||||
|
||||
TypeLoc getPointeeLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<MemberPointerType>(Ty)->getPointeeType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this MemberPointerLoc.
|
||||
@ -362,36 +518,30 @@ class MemberPointerLoc : public DeclaratorLoc {
|
||||
return SourceRange(getStarLoc(), getStarLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getPointeeType(); }
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getPointeeLoc().getFullDataSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const MemberPointerLoc *TL) { return true; }
|
||||
struct ReferenceLocInfo {
|
||||
SourceLocation AmpLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for references.
|
||||
class ReferenceLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation AmpLoc;
|
||||
};
|
||||
|
||||
class ReferenceLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
ReferenceLoc,
|
||||
ReferenceType,
|
||||
ReferenceLocInfo> {
|
||||
public:
|
||||
SourceLocation getAmpLoc() const {
|
||||
return static_cast<Info*>(Data)->AmpLoc;
|
||||
return getLocalData()->AmpLoc;
|
||||
}
|
||||
void setAmpLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->AmpLoc = Loc;
|
||||
getLocalData()->AmpLoc = Loc;
|
||||
}
|
||||
|
||||
TypeLoc getPointeeLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<ReferenceType>(Ty)->getPointeeType(), Next);
|
||||
return TypeLoc(getTypePtr()->getPointeeType(), getNonLocalData());
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this ReferenceLoc.
|
||||
@ -403,48 +553,44 @@ class ReferenceLoc : public DeclaratorLoc {
|
||||
return SourceRange(getAmpLoc(), getAmpLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getPointeeType(); }
|
||||
};
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getPointeeLoc().getFullDataSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const ReferenceLoc *TL) { return true; }
|
||||
struct FunctionLocInfo {
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for functions.
|
||||
class FunctionLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
};
|
||||
class FunctionLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
FunctionLoc,
|
||||
FunctionType,
|
||||
FunctionLocInfo> {
|
||||
// ParmVarDecls* are stored after Info, one for each argument.
|
||||
ParmVarDecl **getParmArray() const {
|
||||
return reinterpret_cast<ParmVarDecl**>(static_cast<Info*>(Data) + 1);
|
||||
return (ParmVarDecl**) getExtraLocalData();
|
||||
}
|
||||
|
||||
public:
|
||||
SourceLocation getLParenLoc() const {
|
||||
return static_cast<Info*>(Data)->LParenLoc;
|
||||
return getLocalData()->LParenLoc;
|
||||
}
|
||||
void setLParenLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->LParenLoc = Loc;
|
||||
getLocalData()->LParenLoc = Loc;
|
||||
}
|
||||
|
||||
SourceLocation getRParenLoc() const {
|
||||
return static_cast<Info*>(Data)->RParenLoc;
|
||||
return getLocalData()->RParenLoc;
|
||||
}
|
||||
void setRParenLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->RParenLoc = Loc;
|
||||
getLocalData()->RParenLoc = Loc;
|
||||
}
|
||||
|
||||
unsigned getNumArgs() const {
|
||||
if (isa<FunctionNoProtoType>(Ty))
|
||||
if (isa<FunctionNoProtoType>(getTypePtr()))
|
||||
return 0;
|
||||
return cast<FunctionProtoType>(Ty)->getNumArgs();
|
||||
return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
|
||||
}
|
||||
ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
|
||||
void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
|
||||
@ -452,8 +598,7 @@ class FunctionLoc : public DeclaratorLoc {
|
||||
TypeLoc getArgLoc(unsigned i) const;
|
||||
|
||||
TypeLoc getResultLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<FunctionType>(Ty)->getResultType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this FunctionLoc.
|
||||
@ -466,50 +611,49 @@ class FunctionLoc : public DeclaratorLoc {
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const {
|
||||
return sizeof(Info) + getNumArgs() * sizeof(ParmVarDecl*);
|
||||
unsigned getExtraLocalDataSize() const {
|
||||
return getNumArgs() * sizeof(ParmVarDecl*);
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getResultLoc().getFullDataSize();
|
||||
}
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getResultType(); }
|
||||
};
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const FunctionLoc *TL) { return true; }
|
||||
|
||||
struct ArrayLocInfo {
|
||||
SourceLocation LBracketLoc, RBracketLoc;
|
||||
Expr *Size;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for arrays.
|
||||
class ArrayLoc : public DeclaratorLoc {
|
||||
struct Info {
|
||||
SourceLocation LBracketLoc, RBracketLoc;
|
||||
Expr *Size;
|
||||
};
|
||||
class ArrayLoc : public ConcreteTypeLoc<DeclaratorLoc,
|
||||
ArrayLoc,
|
||||
ArrayType,
|
||||
ArrayLocInfo> {
|
||||
public:
|
||||
SourceLocation getLBracketLoc() const {
|
||||
return static_cast<Info*>(Data)->LBracketLoc;
|
||||
return getLocalData()->LBracketLoc;
|
||||
}
|
||||
void setLBracketLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->LBracketLoc = Loc;
|
||||
getLocalData()->LBracketLoc = Loc;
|
||||
}
|
||||
|
||||
SourceLocation getRBracketLoc() const {
|
||||
return static_cast<Info*>(Data)->RBracketLoc;
|
||||
return getLocalData()->RBracketLoc;
|
||||
}
|
||||
void setRBracketLoc(SourceLocation Loc) {
|
||||
static_cast<Info*>(Data)->RBracketLoc = Loc;
|
||||
getLocalData()->RBracketLoc = Loc;
|
||||
}
|
||||
|
||||
Expr *getSizeExpr() const {
|
||||
return static_cast<Info*>(Data)->Size;
|
||||
return getLocalData()->Size;
|
||||
}
|
||||
void setSizeExpr(Expr *Size) {
|
||||
static_cast<Info*>(Data)->Size = Size;
|
||||
getLocalData()->Size = Size;
|
||||
}
|
||||
|
||||
TypeLoc getElementLoc() const {
|
||||
void *Next = static_cast<char*>(Data) + getLocalDataSize();
|
||||
return TypeLoc(cast<ArrayType>(Ty)->getElementType(), Next);
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this ArrayLoc.
|
||||
@ -520,17 +664,8 @@ class ArrayLoc : public DeclaratorLoc {
|
||||
return SourceRange(getLBracketLoc(), getRBracketLoc());
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getLocalDataSize() const { return sizeof(Info); }
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() + getElementLoc().getFullDataSize();
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL);
|
||||
static bool classof(const ArrayLoc *TL) { return true; }
|
||||
bool hasInnerType() const { return true; }
|
||||
QualType getInnerType() const { return getTypePtr()->getElementType(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,9 @@
|
||||
// base class (e.g., "TypeSpecLoc" or "DeclaratorLoc"), and the Type subclass
|
||||
// that the TypeLoc is associated with.
|
||||
//
|
||||
// TYPELOC(Class, Base, Type) - Description of the TypeLoc subclass.
|
||||
// TYPELOC(Class, Base) - A TypeLoc subclass.
|
||||
//
|
||||
// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass.
|
||||
//
|
||||
// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc.
|
||||
//
|
||||
@ -23,16 +25,20 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef UNQUAL_TYPELOC
|
||||
# define UNQUAL_TYPELOC(Class, Base, Type) TYPELOC(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef ABSTRACT_TYPELOC
|
||||
# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc, Type)
|
||||
# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc)
|
||||
#endif
|
||||
|
||||
#ifndef TYPESPEC_TYPELOC
|
||||
# define TYPESPEC_TYPELOC(Class, Type) TYPELOC(Class, TypeSpecLoc, Type)
|
||||
# define TYPESPEC_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, TypeSpecLoc, Type)
|
||||
#endif
|
||||
|
||||
#ifndef DECLARATOR_TYPELOC
|
||||
# define DECLARATOR_TYPELOC(Class, Type) TYPELOC(Class, DeclaratorLoc, Type)
|
||||
# define DECLARATOR_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, DeclaratorLoc, Type)
|
||||
#endif
|
||||
|
||||
TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type)
|
||||
@ -47,9 +53,11 @@ DECLARATOR_TYPELOC(FunctionLoc, FunctionType)
|
||||
DECLARATOR_TYPELOC(ArrayLoc, ArrayType)
|
||||
ABSTRACT_TYPELOC(DeclaratorLoc)
|
||||
ABSTRACT_TYPELOC(TypeSpecLoc)
|
||||
TYPELOC(QualifiedLoc, TypeLoc)
|
||||
|
||||
|
||||
#undef DECLARATOR_TYPELOC
|
||||
#undef TYPESPEC_TYPELOC
|
||||
#undef ABSTRACT_TYPELOC
|
||||
#undef UNQUAL_TYPELOC
|
||||
#undef TYPELOC
|
||||
|
@ -25,12 +25,14 @@ template<typename ImplClass, typename RetTy=void>
|
||||
class TypeLocVisitor {
|
||||
class TypeDispatch : public TypeVisitor<TypeDispatch, RetTy> {
|
||||
ImplClass *Impl;
|
||||
TypeLoc TyLoc;
|
||||
UnqualTypeLoc TyLoc;
|
||||
|
||||
public:
|
||||
TypeDispatch(ImplClass *impl, TypeLoc &tyLoc) : Impl(impl), TyLoc(tyLoc) { }
|
||||
TypeDispatch(ImplClass *impl, UnqualTypeLoc &tyLoc)
|
||||
: Impl(impl), TyLoc(tyLoc) { }
|
||||
#define TYPELOC(CLASS, BASE)
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) \
|
||||
#define UNQUAL_TYPELOC(CLASS, PARENT, TYPE) \
|
||||
RetTy Visit##TYPE(TYPE *) { \
|
||||
return Impl->Visit##CLASS(reinterpret_cast<CLASS&>(TyLoc)); \
|
||||
}
|
||||
@ -39,13 +41,22 @@ class TypeLocVisitor {
|
||||
|
||||
public:
|
||||
RetTy Visit(TypeLoc TyLoc) {
|
||||
TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc);
|
||||
return TD.Visit(TyLoc.getSourceType().getTypePtr());
|
||||
if (isa<QualifiedLoc>(TyLoc))
|
||||
return static_cast<ImplClass*>(this)->
|
||||
VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc));
|
||||
|
||||
return Visit(cast<UnqualTypeLoc>(TyLoc));
|
||||
}
|
||||
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) RetTy Visit##CLASS(CLASS TyLoc) { \
|
||||
DISPATCH(PARENT); \
|
||||
}
|
||||
RetTy Visit(UnqualTypeLoc TyLoc) {
|
||||
TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc);
|
||||
return TD.Visit(TyLoc.getSourceTypePtr());
|
||||
}
|
||||
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
RetTy Visit##CLASS(CLASS TyLoc) { \
|
||||
DISPATCH(PARENT); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); }
|
||||
|
@ -936,18 +936,15 @@ def err_template_arg_extra_parens : Error<
|
||||
|
||||
// C++ template specialization
|
||||
def err_template_spec_unknown_kind : Error<
|
||||
"can only provide an explicit %select{<error>|<error>|specialization|"
|
||||
"instantiation|instantiation}0 for a class template, function template, or "
|
||||
"a member function, static data member, or member class of a class template">;
|
||||
"can only provide an explicit specialization for a class template, function "
|
||||
"template, or a member function, static data member, or member class of a "
|
||||
"class template">;
|
||||
def note_specialized_entity : Note<
|
||||
"explicitly %select{<error>|<error>|specialized|instantiated|instantiated}0 "
|
||||
"declaration is here">;
|
||||
"explicitly specialized declaration is here">;
|
||||
def err_template_spec_decl_function_scope : Error<
|
||||
"explicit %select{<error>|<error>|specialization|instantiation|"
|
||||
"instantiation}0 of %1 in function scope">;
|
||||
"explicit specialization of %0 in function scope">;
|
||||
def err_template_spec_decl_class_scope : Error<
|
||||
"explicit %select{<error>|<error>|specialization|instantiation|"
|
||||
"instantiation}0 of %1 in class scope">;
|
||||
"explicit specialization of %0 in class scope">;
|
||||
def err_template_spec_decl_out_of_scope_global : Error<
|
||||
"%select{class template|class template partial|function template|member "
|
||||
"function|static data member|member class}0 specialization of %1 must "
|
||||
@ -1085,6 +1082,9 @@ def note_nontemplate_decl_here : Note<
|
||||
"non-templated declaration is here">;
|
||||
def err_explicit_instantiation_out_of_scope : Error<
|
||||
"explicit instantiation of %0 not in a namespace enclosing %1">;
|
||||
def err_explicit_instantiation_must_be_global : Error<
|
||||
"explicit instantiation of %0 must occur at global scope">;
|
||||
|
||||
def err_explicit_instantiation_requires_name : Error<
|
||||
"explicit instantiation declaration requires a name">;
|
||||
def err_explicit_instantiation_of_typedef : Error<
|
||||
@ -1104,7 +1104,15 @@ def err_explicit_instantiation_ambiguous : Error<
|
||||
"partial ordering for explicit instantiation of %0 is ambiguous">;
|
||||
def note_explicit_instantiation_candidate : Note<
|
||||
"explicit instantiation candidate function template here %0">;
|
||||
|
||||
def err_explicit_instantiation_inline : Error<
|
||||
"explicit instantiation cannot be 'inline'">;
|
||||
def err_explicit_instantiation_without_qualified_id : Error<
|
||||
"qualifier in explicit instantiation of %q0 requires a template-id">;
|
||||
def err_explicit_instantiation_without_qualified_id_quals : Error<
|
||||
"qualifier in explicit instantiation of '%0%1' requires a template-id">;
|
||||
def err_explicit_instantiation_unqualified_wrong_namespace : Error<
|
||||
"explicit instantiation of %q0 must occur in %1">;
|
||||
|
||||
// C++ typename-specifiers
|
||||
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
|
||||
def err_typename_nested_not_type : Error<
|
||||
|
@ -233,9 +233,9 @@ void ASTContext::InitBuiltinTypes() {
|
||||
}
|
||||
|
||||
MemberSpecializationInfo *
|
||||
ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
|
||||
ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
|
||||
assert(Var->isStaticDataMember() && "Not a static data member");
|
||||
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>::iterator Pos
|
||||
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
|
||||
= InstantiatedFromStaticDataMember.find(Var);
|
||||
if (Pos == InstantiatedFromStaticDataMember.end())
|
||||
return 0;
|
||||
|
@ -373,14 +373,30 @@ SourceRange VarDecl::getSourceRange() const {
|
||||
return SourceRange(getLocation(), getLocation());
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
|
||||
bool VarDecl::isOutOfLine() const {
|
||||
if (!isStaticDataMember())
|
||||
return false;
|
||||
|
||||
if (Decl::isOutOfLine())
|
||||
return true;
|
||||
|
||||
// If this static data member was instantiated from a static data member of
|
||||
// a class template, check whether that static data member was defined
|
||||
// out-of-line.
|
||||
if (VarDecl *VD = getInstantiatedFromStaticDataMember())
|
||||
return VD->isOutOfLine();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
|
||||
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
||||
return cast<VarDecl>(MSI->getInstantiatedFrom());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
|
||||
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
|
||||
if (MemberSpecializationInfo *MSI
|
||||
= getASTContext().getInstantiatedFromStaticDataMember(this))
|
||||
return MSI->getTemplateSpecializationKind();
|
||||
@ -388,7 +404,7 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() {
|
||||
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
|
||||
return getASTContext().getInstantiatedFromStaticDataMember(this);
|
||||
}
|
||||
|
||||
@ -809,7 +825,6 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
}
|
||||
|
||||
bool FunctionDecl::isOutOfLine() const {
|
||||
// FIXME: Should we restrict this to member functions?
|
||||
if (Decl::isOutOfLine())
|
||||
return true;
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
using namespace clang;
|
||||
|
||||
@ -24,7 +25,7 @@ namespace {
|
||||
class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) \
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); }
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
@ -42,25 +43,14 @@ SourceRange TypeLoc::getSourceRange() const {
|
||||
return TypeLocRanger().Visit(*this);
|
||||
}
|
||||
|
||||
/// \brief Returns the size of type source info data block for the given type.
|
||||
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
|
||||
return TypeLoc(Ty, 0).getFullDataSize();
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this TypeLoc.
|
||||
TypeSpecLoc TypeLoc::getTypeSpecLoc() const {
|
||||
if (isNull())
|
||||
return TypeSpecLoc();
|
||||
|
||||
if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(this))
|
||||
UnqualTypeLoc Cur = getUnqualifiedLoc();
|
||||
if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur))
|
||||
return DL->getTypeSpecLoc();
|
||||
return cast<TypeSpecLoc>(*this);
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this TypeLoc and return its
|
||||
/// SourceRange.
|
||||
SourceRange TypeLoc::getTypeSpecRange() const {
|
||||
return getTypeSpecLoc().getSourceRange();
|
||||
return cast<TypeSpecLoc>(Cur);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -69,7 +59,7 @@ namespace {
|
||||
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) \
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); }
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
@ -82,9 +72,9 @@ class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned TypeLoc::getFullDataSize() const {
|
||||
if (isNull()) return 0;
|
||||
return TypeSizer().Visit(*this);
|
||||
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
|
||||
if (Ty.isNull()) return 0;
|
||||
return TypeSizer().Visit(TypeLoc(Ty, 0));
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -93,13 +83,16 @@ namespace {
|
||||
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
|
||||
class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
|
||||
public:
|
||||
#define TYPELOC(CLASS, PARENT, TYPE)
|
||||
#define TYPELOC(CLASS, PARENT)
|
||||
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
|
||||
TypeLoc Visit##CLASS(CLASS TyLoc);
|
||||
TypeLoc Visit##CLASS(CLASS TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); }
|
||||
TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
|
||||
TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
return TyLoc.getUnqualifiedLoc();
|
||||
}
|
||||
|
||||
TypeLoc VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A declarator loc wrapper was not handled!");
|
||||
@ -135,7 +128,10 @@ TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) {
|
||||
/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
|
||||
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
|
||||
TypeLoc TypeLoc::getNextTypeLoc() const {
|
||||
return NextLoc().Visit(*this);
|
||||
//llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n";
|
||||
TypeLoc Tmp = NextLoc().Visit(*this);
|
||||
//llvm::errs() << " result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n";
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -150,7 +146,7 @@ class TypeSpecChecker : public TypeLocVisitor<TypeSpecChecker, bool> {
|
||||
|
||||
}
|
||||
|
||||
bool TypeSpecLoc::classof(const TypeLoc *TL) {
|
||||
bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) {
|
||||
return TypeSpecChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
@ -163,7 +159,7 @@ namespace {
|
||||
/// \brief Return the TypeSpecLoc for the visited DeclaratorLoc.
|
||||
class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> {
|
||||
public:
|
||||
#define TYPELOC(CLASS, PARENT, TYPE)
|
||||
#define TYPELOC(CLASS, PARENT)
|
||||
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
|
||||
TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); }
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
@ -172,6 +168,10 @@ class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> {
|
||||
assert(0 && "A declarator loc wrapper was not handled!");
|
||||
return TypeSpecLoc();
|
||||
}
|
||||
|
||||
TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
return Visit(TyLoc.getUnqualifiedLoc());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -190,7 +190,7 @@ class DeclaratorLocChecker : public TypeLocVisitor<DeclaratorLocChecker, bool> {
|
||||
|
||||
}
|
||||
|
||||
bool DeclaratorLoc::classof(const TypeLoc *TL) {
|
||||
bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) {
|
||||
return DeclaratorLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
@ -208,163 +208,8 @@ class DefaultTypeSpecLocChecker :
|
||||
|
||||
}
|
||||
|
||||
bool DefaultTypeSpecLoc::classof(const TypeLoc *TL) {
|
||||
return DefaultTypeSpecLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TypedefLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class TypedefLocChecker : public TypeLocVisitor<TypedefLocChecker, bool> {
|
||||
public:
|
||||
bool VisitTypedefLoc(TypedefLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool TypedefLoc::classof(const TypeLoc *TL) {
|
||||
return TypedefLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ObjCInterfaceLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class ObjCInterfaceLocChecker :
|
||||
public TypeLocVisitor<ObjCInterfaceLocChecker, bool> {
|
||||
public:
|
||||
bool VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool ObjCInterfaceLoc::classof(const TypeLoc *TL) {
|
||||
return ObjCInterfaceLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ObjCProtocolListLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class ObjCProtocolListLocChecker :
|
||||
public TypeLocVisitor<ObjCProtocolListLocChecker, bool> {
|
||||
public:
|
||||
bool VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool ObjCProtocolListLoc::classof(const TypeLoc *TL) {
|
||||
return ObjCProtocolListLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PointerLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class PointerLocChecker : public TypeLocVisitor<PointerLocChecker, bool> {
|
||||
public:
|
||||
bool VisitPointerLoc(PointerLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool PointerLoc::classof(const TypeLoc *TL) {
|
||||
return PointerLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BlockPointerLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class BlockPointerLocChecker :
|
||||
public TypeLocVisitor<BlockPointerLocChecker, bool> {
|
||||
public:
|
||||
bool VisitBlockPointerLoc(BlockPointerLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool BlockPointerLoc::classof(const TypeLoc *TL) {
|
||||
return BlockPointerLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MemberPointerLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class MemberPointerLocChecker :
|
||||
public TypeLocVisitor<MemberPointerLocChecker, bool> {
|
||||
public:
|
||||
bool VisitMemberPointerLoc(MemberPointerLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool MemberPointerLoc::classof(const TypeLoc *TL) {
|
||||
return MemberPointerLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ReferenceLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class ReferenceLocChecker : public TypeLocVisitor<ReferenceLocChecker, bool> {
|
||||
public:
|
||||
bool VisitReferenceLoc(ReferenceLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool ReferenceLoc::classof(const TypeLoc *TL) {
|
||||
return ReferenceLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FunctionLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class FunctionLocChecker : public TypeLocVisitor<FunctionLocChecker, bool> {
|
||||
public:
|
||||
bool VisitFunctionLoc(FunctionLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool FunctionLoc::classof(const TypeLoc *TL) {
|
||||
return FunctionLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ArrayLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class ArrayLocChecker : public TypeLocVisitor<ArrayLocChecker, bool> {
|
||||
public:
|
||||
bool VisitArrayLoc(ArrayLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool ArrayLoc::classof(const TypeLoc *TL) {
|
||||
return ArrayLocChecker().Visit(*TL);
|
||||
bool DefaultTypeSpecLoc::classofType(const Type *Ty) {
|
||||
return
|
||||
DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0));
|
||||
}
|
||||
|
||||
|
@ -3232,10 +3232,8 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
|
||||
// returned object is suppose to be an Objective-C object, we have
|
||||
// a leak (as the caller expects a GC'ed object) because no
|
||||
// method should return ownership unless it returns a CF object.
|
||||
X = X ^ RefVal::ErrorGCLeakReturned;
|
||||
|
||||
// Keep this false until this is properly tested.
|
||||
hasError = true;
|
||||
X = X ^ RefVal::ErrorGCLeakReturned;
|
||||
}
|
||||
else if (!RE.isOwned()) {
|
||||
// Either we are using GC and the returned object is a CF type
|
||||
|
@ -1115,28 +1115,6 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
|
||||
}
|
||||
}
|
||||
|
||||
// Special case: the current region represents a cast and it and the super
|
||||
// region both have pointer types or intptr_t types. If so, perform the
|
||||
// retrieve from the super region and appropriately "cast" the value.
|
||||
// This is needed to support OSAtomicCompareAndSwap and friends or other
|
||||
// loads that treat integers as pointers and vis versa.
|
||||
if (R->getIndex().isZeroConstant()) {
|
||||
if (const TypedRegion *superTR = dyn_cast<TypedRegion>(superR)) {
|
||||
ASTContext &Ctx = getContext();
|
||||
if (IsAnyPointerOrIntptr(superTR->getValueType(Ctx), Ctx)) {
|
||||
QualType valTy = R->getValueType(Ctx);
|
||||
if (IsAnyPointerOrIntptr(valTy, Ctx)) {
|
||||
// Retrieve the value from the super region. This will be casted to
|
||||
// valTy when we return to 'Retrieve'.
|
||||
const SValuator::CastResult &cr = Retrieve(state,
|
||||
loc::MemRegionVal(superR),
|
||||
valTy);
|
||||
return cr.getSVal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the immediate super region has a direct binding.
|
||||
if (Optional<SVal> V = getDirectBinding(B, superR)) {
|
||||
if (SymbolRef parentSym = V->getAsSymbol())
|
||||
|
@ -78,6 +78,26 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,
|
||||
RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
QualType DestType,
|
||||
bool IsInitializer) {
|
||||
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
|
||||
// If we shouldn't destroy the temporaries, just emit the
|
||||
// child expression.
|
||||
if (!TE->shouldDestroyTemporaries())
|
||||
return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
|
||||
IsInitializer);
|
||||
|
||||
// Keep track of the current cleanup stack depth.
|
||||
unsigned OldNumLiveTemporaries = LiveTemporaries.size();
|
||||
|
||||
RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
|
||||
IsInitializer);
|
||||
|
||||
// Pop temporaries.
|
||||
while (LiveTemporaries.size() > OldNumLiveTemporaries)
|
||||
PopCXXTemporary();
|
||||
|
||||
return RV;
|
||||
}
|
||||
|
||||
RValue Val;
|
||||
if (E->isLvalue(getContext()) == Expr::LV_Valid) {
|
||||
// Emit the expr as an lvalue.
|
||||
@ -86,9 +106,21 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
return RValue::get(LV.getAddress());
|
||||
Val = EmitLoadOfLValue(LV, E->getType());
|
||||
} else {
|
||||
// FIXME: Initializers don't work with casts yet. For example
|
||||
// const A& a = B();
|
||||
// if B inherits from A.
|
||||
const CXXRecordDecl *BaseClassDecl = 0;
|
||||
const CXXRecordDecl *DerivedClassDecl = 0;
|
||||
|
||||
if (const CastExpr *CE =
|
||||
dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) {
|
||||
if (CE->getCastKind() == CastExpr::CK_DerivedToBase) {
|
||||
E = CE->getSubExpr();
|
||||
|
||||
BaseClassDecl =
|
||||
cast<CXXRecordDecl>(CE->getType()->getAs<RecordType>()->getDecl());
|
||||
DerivedClassDecl =
|
||||
cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
|
||||
}
|
||||
}
|
||||
|
||||
Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
|
||||
IsInitializer);
|
||||
|
||||
@ -106,6 +138,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if need to perform the derived-to-base cast.
|
||||
if (BaseClassDecl) {
|
||||
llvm::Value *Derived = Val.getAggregateAddr();
|
||||
|
||||
llvm::Value *Base =
|
||||
GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl,
|
||||
/*NullCheckValue=*/false);
|
||||
return RValue::get(Base);
|
||||
}
|
||||
}
|
||||
|
||||
if (Val.isAggregate()) {
|
||||
|
@ -56,6 +56,8 @@ class VtableBuilder {
|
||||
const bool Extern;
|
||||
const uint32_t LLVMPointerWidth;
|
||||
Index_t extra;
|
||||
int CurrentVBaseOffset;
|
||||
typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
|
||||
public:
|
||||
VtableBuilder(std::vector<llvm::Constant *> &meth,
|
||||
const CXXRecordDecl *c,
|
||||
@ -63,7 +65,8 @@ class VtableBuilder {
|
||||
: methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
|
||||
rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
|
||||
CGM(cgm), Extern(true),
|
||||
LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
|
||||
LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)),
|
||||
CurrentVBaseOffset(0) {
|
||||
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
|
||||
}
|
||||
|
||||
@ -187,7 +190,10 @@ class VtableBuilder {
|
||||
VCall[MD] = idx;
|
||||
CallOffset ThisOffset;
|
||||
// FIXME: calculate non-virtual offset
|
||||
ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8));
|
||||
ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */,
|
||||
-((idx+extra+2)*LLVMPointerWidth/8));
|
||||
// FIXME: Do we always have to build a covariant thunk to save oret,
|
||||
// which is the containing virtual base class?
|
||||
if (ReturnOffset.first || ReturnOffset.second)
|
||||
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
|
||||
ReturnOffset),
|
||||
@ -199,6 +205,7 @@ class VtableBuilder {
|
||||
|
||||
// FIXME: finish off
|
||||
int64_t O = VCallOffset[OMD] - Offset/8;
|
||||
// int64_t O = CurrentVBaseOffset/8 - Offset/8;
|
||||
if (O || ReturnOffset.first || ReturnOffset.second) {
|
||||
CallOffset ThisOffset = std::make_pair(O, 0);
|
||||
|
||||
@ -241,10 +248,8 @@ class VtableBuilder {
|
||||
CovariantThunks.clear();
|
||||
}
|
||||
|
||||
void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> > *Path, bool MorallyVirtual) {
|
||||
for (std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> >::reverse_iterator i =Path->rbegin(),
|
||||
void OverrideMethods(Path_t *Path, bool MorallyVirtual) {
|
||||
for (Path_t::reverse_iterator i = Path->rbegin(),
|
||||
e = Path->rend(); i != e; ++i) {
|
||||
const CXXRecordDecl *RD = i->first;
|
||||
int64_t Offset = i->second;
|
||||
@ -314,7 +319,8 @@ class VtableBuilder {
|
||||
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
|
||||
const CXXRecordDecl *PrimaryBase,
|
||||
bool PrimaryBaseWasVirtual, bool MorallyVirtual,
|
||||
int64_t Offset) {
|
||||
int64_t Offset, Path_t *Path) {
|
||||
Path->push_back(std::make_pair(RD, Offset));
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
if (i->isVirtual())
|
||||
@ -324,41 +330,65 @@ class VtableBuilder {
|
||||
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
|
||||
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
|
||||
StartNewTable();
|
||||
std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> > S;
|
||||
S.push_back(std::make_pair(RD, Offset));
|
||||
GenerateVtableForBase(Base, MorallyVirtual, o, false, &S);
|
||||
CurrentVBaseOffset = Offset;
|
||||
GenerateVtableForBase(Base, MorallyVirtual, o, false, Path);
|
||||
}
|
||||
}
|
||||
Path->pop_back();
|
||||
}
|
||||
|
||||
// #define D(X) do { X; } while (0)
|
||||
#define D(X)
|
||||
|
||||
void insertVCalls(int InsertionPoint) {
|
||||
llvm::Constant *e = 0;
|
||||
D(VCalls.insert(VCalls.begin(), 673));
|
||||
D(VCalls.push_back(672));
|
||||
methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e);
|
||||
// The vcalls come first...
|
||||
for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
|
||||
e = VCalls.rend();
|
||||
i != e; ++i)
|
||||
methods[InsertionPoint++] = wrap((0?600:0) + *i);
|
||||
VCalls.clear();
|
||||
}
|
||||
|
||||
Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets,
|
||||
const ASTRecordLayout &Layout,
|
||||
const CXXRecordDecl *PrimaryBase,
|
||||
bool PrimaryBaseWasVirtual, bool MorallyVirtual,
|
||||
int64_t Offset, bool ForVirtualBase) {
|
||||
int64_t Offset, bool ForVirtualBase, Path_t *Path) {
|
||||
bool alloc = false;
|
||||
if (Path == 0) {
|
||||
alloc = true;
|
||||
Path = new Path_t;
|
||||
}
|
||||
|
||||
StartNewTable();
|
||||
extra = 0;
|
||||
// FIXME: Cleanup.
|
||||
if (!ForVirtualBase) {
|
||||
D(methods.push_back(wrap(666)));
|
||||
// then virtual base offsets...
|
||||
for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
|
||||
e = offsets.rend(); i != e; ++i)
|
||||
methods.push_back(*i);
|
||||
D(methods.push_back(wrap(667)));
|
||||
}
|
||||
|
||||
// The vcalls come first...
|
||||
for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(),
|
||||
e=VCalls.rend();
|
||||
i != e; ++i)
|
||||
methods.push_back(wrap((0?600:0) + *i));
|
||||
VCalls.clear();
|
||||
bool DeferVCalls = MorallyVirtual || ForVirtualBase;
|
||||
int VCallInsertionPoint = methods.size();
|
||||
if (!DeferVCalls) {
|
||||
insertVCalls(VCallInsertionPoint);
|
||||
}
|
||||
|
||||
if (ForVirtualBase) {
|
||||
D(methods.push_back(wrap(668)));
|
||||
// then virtual base offsets...
|
||||
for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
|
||||
e = offsets.rend(); i != e; ++i)
|
||||
methods.push_back(*i);
|
||||
D(methods.push_back(wrap(669)));
|
||||
}
|
||||
|
||||
methods.push_back(wrap(-(Offset/8)));
|
||||
@ -371,7 +401,18 @@ class VtableBuilder {
|
||||
|
||||
// and then the non-virtual bases.
|
||||
NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
|
||||
MorallyVirtual, Offset);
|
||||
MorallyVirtual, Offset, Path);
|
||||
|
||||
if (ForVirtualBase) {
|
||||
D(methods.push_back(wrap(670)));
|
||||
insertVCalls(VCallInsertionPoint);
|
||||
AddressPoint += VCalls.size();
|
||||
D(methods.push_back(wrap(671)));
|
||||
}
|
||||
|
||||
if (alloc) {
|
||||
delete Path;
|
||||
}
|
||||
return AddressPoint;
|
||||
}
|
||||
|
||||
@ -397,8 +438,7 @@ class VtableBuilder {
|
||||
int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
|
||||
bool MorallyVirtual = false, int64_t Offset = 0,
|
||||
bool ForVirtualBase = false,
|
||||
std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> > *Path = 0) {
|
||||
Path_t *Path = 0) {
|
||||
if (!RD->isDynamicClass())
|
||||
return 0;
|
||||
|
||||
@ -426,18 +466,16 @@ class VtableBuilder {
|
||||
OverrideMethods(Path, MorallyVirtual);
|
||||
|
||||
return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
|
||||
MorallyVirtual, Offset, ForVirtualBase);
|
||||
MorallyVirtual, Offset, ForVirtualBase, Path);
|
||||
}
|
||||
|
||||
void GenerateVtableForVBases(const CXXRecordDecl *RD,
|
||||
int64_t Offset = 0,
|
||||
std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> > *Path = 0) {
|
||||
Path_t *Path = 0) {
|
||||
bool alloc = false;
|
||||
if (Path == 0) {
|
||||
alloc = true;
|
||||
Path = new std::vector<std::pair<const CXXRecordDecl *,
|
||||
int64_t> >;
|
||||
Path = new Path_t;
|
||||
}
|
||||
// FIXME: We also need to override using all paths to a virtual base,
|
||||
// right now, we just process the first path
|
||||
@ -450,14 +488,18 @@ class VtableBuilder {
|
||||
// Mark it so we don't output it twice.
|
||||
IndirectPrimary.insert(Base);
|
||||
StartNewTable();
|
||||
VCall.clear();
|
||||
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
|
||||
CurrentVBaseOffset = BaseOffset;
|
||||
GenerateVtableForBase(Base, true, BaseOffset, true, Path);
|
||||
}
|
||||
int64_t BaseOffset = Offset;
|
||||
if (i->isVirtual())
|
||||
BaseOffset = BLayout.getVBaseClassOffset(Base);
|
||||
if (Base->getNumVBases())
|
||||
if (Base->getNumVBases()) {
|
||||
CurrentVBaseOffset = BaseOffset;
|
||||
GenerateVtableForVBases(Base, BaseOffset, Path);
|
||||
}
|
||||
}
|
||||
Path->pop_back();
|
||||
if (alloc)
|
||||
|
@ -541,7 +541,12 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
|
||||
}
|
||||
}
|
||||
|
||||
return VD->getStorageClass() == VarDecl::Static;
|
||||
// Static data may be deferred, but out-of-line static data members
|
||||
// cannot be.
|
||||
// FIXME: What if the initializer has side effects?
|
||||
return VD->isInAnonymousNamespace() ||
|
||||
(VD->getStorageClass() == VarDecl::Static &&
|
||||
!(VD->isStaticDataMember() && VD->isOutOfLine()));
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
|
||||
@ -928,6 +933,37 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
|
||||
EmitGlobalVarDefinition(D);
|
||||
}
|
||||
|
||||
static CodeGenModule::GVALinkage
|
||||
GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
|
||||
// Everything located semantically within an anonymous namespace is
|
||||
// always internal.
|
||||
if (VD->isInAnonymousNamespace())
|
||||
return CodeGenModule::GVA_Internal;
|
||||
|
||||
// Handle linkage for static data members.
|
||||
if (VD->isStaticDataMember()) {
|
||||
switch (VD->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
assert(false && "Variable should not be instantiated");
|
||||
// Fall through to treat this like any other instantiation.
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
return CodeGenModule::GVA_TemplateInstantiation;
|
||||
}
|
||||
}
|
||||
|
||||
// Static variables get internal linkage.
|
||||
if (VD->getStorageClass() == VarDecl::Static)
|
||||
return CodeGenModule::GVA_Internal;
|
||||
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
llvm::Constant *Init = 0;
|
||||
QualType ASTTy = D->getType();
|
||||
@ -1021,9 +1057,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
GV->setAlignment(getContext().getDeclAlignInBytes(D));
|
||||
|
||||
// Set the llvm linkage type as appropriate.
|
||||
if (D->isInAnonymousNamespace())
|
||||
GV->setLinkage(llvm::Function::InternalLinkage);
|
||||
else if (D->getStorageClass() == VarDecl::Static)
|
||||
GVALinkage Linkage = GetLinkageForVariable(getContext(), D);
|
||||
if (Linkage == GVA_Internal)
|
||||
GV->setLinkage(llvm::Function::InternalLinkage);
|
||||
else if (D->hasAttr<DLLImportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLImportLinkage);
|
||||
@ -1034,7 +1069,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage);
|
||||
else
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
|
||||
} else if (!CompileOpts.NoCommon &&
|
||||
} else if (Linkage == GVA_TemplateInstantiation)
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
|
||||
else if (!CompileOpts.NoCommon &&
|
||||
!D->hasExternalStorage() && !D->getInit() &&
|
||||
!D->getAttr<SectionAttr>()) {
|
||||
GV->setLinkage(llvm::GlobalVariable::CommonLinkage);
|
||||
|
@ -162,7 +162,7 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
|
||||
: Reader(Reader), Record(Record), Idx(Idx) { }
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) \
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS(CLASS TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
@ -173,6 +173,9 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
|
||||
|
||||
}
|
||||
|
||||
void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
// nothing to do
|
||||
}
|
||||
void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
|
||||
TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
: Writer(Writer), Record(Record) { }
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT, TYPE) \
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS(CLASS TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
@ -171,6 +171,9 @@ class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
|
||||
}
|
||||
|
||||
void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
// nothing to do here
|
||||
}
|
||||
void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getStartLoc(), Record);
|
||||
}
|
||||
|
@ -1836,7 +1836,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
|
||||
if (RD->isAbstract())
|
||||
AbstractClassUsageDiagnoser(*this, RD);
|
||||
|
||||
if (!RD->isDependentType())
|
||||
if (!RD->isDependentType() && !RD->isInvalidDecl())
|
||||
AddImplicitlyDeclaredMembersToClass(RD);
|
||||
}
|
||||
|
||||
|
@ -2917,15 +2917,18 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
||||
if (BO->getOpcode() == BinaryOperator::PtrMemD ||
|
||||
BO->getOpcode() == BinaryOperator::PtrMemI) {
|
||||
const FunctionProtoType *FPT = cast<FunctionProtoType>(BO->getType());
|
||||
QualType ReturnTy = FPT->getResultType();
|
||||
QualType ResultTy = FPT->getResultType().getNonReferenceType();
|
||||
|
||||
CXXMemberCallExpr *CE =
|
||||
new (Context) CXXMemberCallExpr(Context, BO, Args, NumArgs,
|
||||
ReturnTy.getNonReferenceType(),
|
||||
RParenLoc);
|
||||
|
||||
ExprOwningPtr<CXXMemberCallExpr> TheCall(this, CE);
|
||||
ExprOwningPtr<CXXMemberCallExpr>
|
||||
TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
|
||||
NumArgs, ResultTy,
|
||||
RParenLoc));
|
||||
|
||||
if (CheckCallReturnType(FPT->getResultType(),
|
||||
BO->getRHS()->getSourceRange().getBegin(),
|
||||
TheCall.get(), 0))
|
||||
return ExprError();
|
||||
|
||||
if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
|
||||
RParenLoc))
|
||||
return ExprError();
|
||||
|
@ -2398,12 +2398,11 @@ static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
/// \brief Check whether a specialization or explicit instantiation is
|
||||
/// well-formed in the current context.
|
||||
/// \brief Check whether a specialization is well-formed in the current
|
||||
/// context.
|
||||
///
|
||||
/// This routine determines whether a template specialization or
|
||||
/// explicit instantiation can be declared in the current context
|
||||
/// (C++ [temp.expl.spec]p2, C++0x [temp.explicit]p2).
|
||||
/// This routine determines whether a template specialization can be declared
|
||||
/// in the current context (C++ [temp.expl.spec]p2).
|
||||
///
|
||||
/// \param S the semantic analysis object for which this check is being
|
||||
/// performed.
|
||||
@ -2421,17 +2420,13 @@ static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
|
||||
/// \param IsPartialSpecialization whether this is a partial specialization of
|
||||
/// a class template.
|
||||
///
|
||||
/// \param TSK the kind of specialization or implicit instantiation being
|
||||
/// performed.
|
||||
///
|
||||
/// \returns true if there was an error that we cannot recover from, false
|
||||
/// otherwise.
|
||||
static bool CheckTemplateSpecializationScope(Sema &S,
|
||||
NamedDecl *Specialized,
|
||||
NamedDecl *PrevDecl,
|
||||
SourceLocation Loc,
|
||||
bool IsPartialSpecialization,
|
||||
TemplateSpecializationKind TSK) {
|
||||
bool IsPartialSpecialization) {
|
||||
// Keep these "kind" numbers in sync with the %select statements in the
|
||||
// various diagnostics emitted by this routine.
|
||||
int EntityKind = 0;
|
||||
@ -2449,8 +2444,8 @@ static bool CheckTemplateSpecializationScope(Sema &S,
|
||||
else if (isa<RecordDecl>(Specialized))
|
||||
EntityKind = 5;
|
||||
else {
|
||||
S.Diag(Loc, diag::err_template_spec_unknown_kind) << TSK;
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity) << TSK;
|
||||
S.Diag(Loc, diag::err_template_spec_unknown_kind);
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2469,13 +2464,13 @@ static bool CheckTemplateSpecializationScope(Sema &S,
|
||||
// declared.
|
||||
if (S.CurContext->getLookupContext()->isFunctionOrMethod()) {
|
||||
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
|
||||
<< TSK << Specialized;
|
||||
<< Specialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (S.CurContext->isRecord() && !IsPartialSpecialization) {
|
||||
S.Diag(Loc, diag::err_template_spec_decl_class_scope)
|
||||
<< TSK << Specialized;
|
||||
<< Specialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2487,43 +2482,36 @@ static bool CheckTemplateSpecializationScope(Sema &S,
|
||||
DeclContext *SpecializedContext
|
||||
= Specialized->getDeclContext()->getEnclosingNamespaceContext();
|
||||
DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
|
||||
if (TSK == TSK_ExplicitSpecialization) {
|
||||
if ((!PrevDecl ||
|
||||
getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
|
||||
getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
|
||||
// There is no prior declaration of this entity, so this
|
||||
// specialization must be in the same context as the template
|
||||
// itself.
|
||||
if (!DC->Equals(SpecializedContext)) {
|
||||
if (isa<TranslationUnitDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
|
||||
<< EntityKind << Specialized;
|
||||
else if (isa<NamespaceDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope)
|
||||
<< EntityKind << Specialized
|
||||
<< cast<NamedDecl>(SpecializedContext);
|
||||
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity)
|
||||
<< TSK;
|
||||
ComplainedAboutScope = true;
|
||||
}
|
||||
if ((!PrevDecl ||
|
||||
getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
|
||||
getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
|
||||
// There is no prior declaration of this entity, so this
|
||||
// specialization must be in the same context as the template
|
||||
// itself.
|
||||
if (!DC->Equals(SpecializedContext)) {
|
||||
if (isa<TranslationUnitDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
|
||||
<< EntityKind << Specialized;
|
||||
else if (isa<NamespaceDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope)
|
||||
<< EntityKind << Specialized
|
||||
<< cast<NamedDecl>(SpecializedContext);
|
||||
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
|
||||
ComplainedAboutScope = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that this redeclaration (or definition) occurs in an enclosing
|
||||
// namespace. We perform this check for explicit specializations and, in
|
||||
// C++0x, for explicit instantiations as well (per DR275).
|
||||
// FIXME: -Wc++0x should make these warnings.
|
||||
// namespace.
|
||||
// Note that HandleDeclarator() performs this check for explicit
|
||||
// specializations of function templates, static data members, and member
|
||||
// functions, so we skip the check here for those kinds of entities.
|
||||
// FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
|
||||
// Should we refactor that check, so that it occurs later?
|
||||
if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
|
||||
((TSK == TSK_ExplicitSpecialization &&
|
||||
!(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
|
||||
isa<FunctionDecl>(Specialized))) ||
|
||||
S.getLangOptions().CPlusPlus0x)) {
|
||||
!(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
|
||||
isa<FunctionDecl>(Specialized))) {
|
||||
if (isa<TranslationUnitDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
|
||||
<< EntityKind << Specialized;
|
||||
@ -2532,7 +2520,7 @@ static bool CheckTemplateSpecializationScope(Sema &S,
|
||||
<< EntityKind << Specialized
|
||||
<< cast<NamedDecl>(SpecializedContext);
|
||||
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity) << TSK;
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
|
||||
}
|
||||
|
||||
// FIXME: check for specialization-after-instantiation errors and such.
|
||||
@ -2835,8 +2823,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
||||
// the current scope.
|
||||
if (TUK != TUK_Friend &&
|
||||
CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
|
||||
TemplateNameLoc, isPartialSpecialization,
|
||||
TSK_ExplicitSpecialization))
|
||||
TemplateNameLoc,
|
||||
isPartialSpecialization))
|
||||
return true;
|
||||
|
||||
// The canonical type
|
||||
@ -3146,7 +3134,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
if (CheckTemplateSpecializationScope(*this,
|
||||
Specialization->getPrimaryTemplate(),
|
||||
Specialization, FD->getLocation(),
|
||||
false, TSK_ExplicitSpecialization))
|
||||
false))
|
||||
return true;
|
||||
|
||||
// C++ [temp.expl.spec]p6:
|
||||
@ -3273,7 +3261,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
|
||||
if (CheckTemplateSpecializationScope(*this,
|
||||
InstantiatedFrom,
|
||||
Instantiation, Member->getLocation(),
|
||||
false, TSK_ExplicitSpecialization))
|
||||
false))
|
||||
return true;
|
||||
|
||||
// Note that this is an explicit instantiation of a member.
|
||||
@ -3325,6 +3313,68 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Check the scope of an explicit instantiation.
|
||||
static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
|
||||
SourceLocation InstLoc,
|
||||
bool WasQualifiedName) {
|
||||
DeclContext *ExpectedContext
|
||||
= D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
|
||||
DeclContext *CurContext = S.CurContext->getLookupContext();
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// An explicit instantiation shall appear in an enclosing namespace of its
|
||||
// template.
|
||||
//
|
||||
// This is DR275, which we do not retroactively apply to C++98/03.
|
||||
if (S.getLangOptions().CPlusPlus0x &&
|
||||
!CurContext->Encloses(ExpectedContext)) {
|
||||
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ExpectedContext))
|
||||
S.Diag(InstLoc, diag::err_explicit_instantiation_out_of_scope)
|
||||
<< D << NS;
|
||||
else
|
||||
S.Diag(InstLoc, diag::err_explicit_instantiation_must_be_global)
|
||||
<< D;
|
||||
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
|
||||
return;
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the name declared in the explicit instantiation is an unqualified
|
||||
// name, the explicit instantiation shall appear in the namespace where
|
||||
// its template is declared or, if that namespace is inline (7.3.1), any
|
||||
// namespace from its enclosing namespace set.
|
||||
if (WasQualifiedName)
|
||||
return;
|
||||
|
||||
if (CurContext->Equals(ExpectedContext))
|
||||
return;
|
||||
|
||||
S.Diag(InstLoc, diag::err_explicit_instantiation_unqualified_wrong_namespace)
|
||||
<< D << ExpectedContext;
|
||||
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given scope specifier has a template-id in it.
|
||||
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
|
||||
if (!SS.isSet())
|
||||
return false;
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the explicit instantiation is for a member function, a member class
|
||||
// or a static data member of a class template specialization, the name of
|
||||
// the class template specialization in the qualified-id for the member
|
||||
// name shall be a simple-template-id.
|
||||
//
|
||||
// C++98 has the same restriction, just worded differently.
|
||||
for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
|
||||
NNS; NNS = NNS->getPrefix())
|
||||
if (Type *T = NNS->getAsType())
|
||||
if (isa<TemplateSpecializationType>(T))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Explicit instantiation of a class template specialization
|
||||
// FIXME: Implement extern template semantics
|
||||
Sema::DeclResult
|
||||
@ -3367,6 +3417,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// There are two forms of explicit instantiation: an explicit instantiation
|
||||
// definition and an explicit instantiation declaration. An explicit
|
||||
// instantiation declaration begins with the extern keyword. [...]
|
||||
TemplateSpecializationKind TSK
|
||||
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
|
||||
: TSK_ExplicitInstantiationDeclaration;
|
||||
@ -3404,10 +3458,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
// namespace of its template. [...]
|
||||
//
|
||||
// This is C++ DR 275.
|
||||
if (CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
|
||||
TemplateNameLoc, false,
|
||||
TSK))
|
||||
return true;
|
||||
CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
|
||||
SS.isSet());
|
||||
|
||||
ClassTemplateSpecializationDecl *Specialization = 0;
|
||||
|
||||
@ -3563,7 +3615,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
|
||||
if (Tag->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
|
||||
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
|
||||
if (!Pattern) {
|
||||
@ -3573,26 +3625,30 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
return true;
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the explicit instantiation is for a class or member class, the
|
||||
// elaborated-type-specifier in the declaration shall include a
|
||||
// simple-template-id.
|
||||
//
|
||||
// C++98 has the same restriction, just worded differently.
|
||||
if (!ScopeSpecifierHasTemplateId(SS))
|
||||
Diag(TemplateLoc, diag::err_explicit_instantiation_without_qualified_id)
|
||||
<< Record << SS.getRange();
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// There are two forms of explicit instantiation: an explicit instantiation
|
||||
// definition and an explicit instantiation declaration. An explicit
|
||||
// instantiation declaration begins with the extern keyword. [...]
|
||||
TemplateSpecializationKind TSK
|
||||
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
|
||||
: TSK_ExplicitInstantiationDeclaration;
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// [...] An explicit instantiation shall appear in an enclosing
|
||||
// namespace of its template. [...]
|
||||
//
|
||||
// This is C++ DR 275.
|
||||
if (getLangOptions().CPlusPlus0x) {
|
||||
// FIXME: In C++98, we would like to turn these errors into warnings,
|
||||
// dependent on a -Wc++0x flag.
|
||||
DeclContext *PatternContext
|
||||
= Pattern->getDeclContext()->getEnclosingNamespaceContext();
|
||||
if (!CurContext->Encloses(PatternContext)) {
|
||||
Diag(TemplateLoc, diag::err_explicit_instantiation_out_of_scope)
|
||||
<< Record << cast<NamedDecl>(PatternContext) << SS.getRange();
|
||||
Diag(Pattern->getLocation(), diag::note_previous_declaration);
|
||||
}
|
||||
}
|
||||
|
||||
TemplateSpecializationKind TSK
|
||||
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
|
||||
: TSK_ExplicitInstantiationDeclaration;
|
||||
CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
|
||||
|
||||
if (!Record->getDefinition(Context)) {
|
||||
// If the class has a definition, instantiate it (and all of its
|
||||
@ -3647,11 +3703,27 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine what kind of explicit instantiation we have.
|
||||
// C++0x [temp.explicit]p1:
|
||||
// [...] An explicit instantiation of a function template shall not use the
|
||||
// inline or constexpr specifiers.
|
||||
// Presumably, this also applies to member functions of class templates as
|
||||
// well.
|
||||
if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
|
||||
Diag(D.getDeclSpec().getInlineSpecLoc(),
|
||||
diag::err_explicit_instantiation_inline)
|
||||
<< CodeModificationHint::CreateRemoval(
|
||||
SourceRange(D.getDeclSpec().getInlineSpecLoc()));
|
||||
|
||||
// FIXME: check for constexpr specifier.
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// There are two forms of explicit instantiation: an explicit instantiation
|
||||
// definition and an explicit instantiation declaration. An explicit
|
||||
// instantiation declaration begins with the extern keyword. [...]
|
||||
TemplateSpecializationKind TSK
|
||||
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
|
||||
: TSK_ExplicitInstantiationDeclaration;
|
||||
|
||||
|
||||
LookupResult Previous;
|
||||
LookupParsedName(Previous, S, &D.getCXXScopeSpec(),
|
||||
Name, LookupOrdinaryName);
|
||||
@ -3688,6 +3760,21 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
return true;
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the explicit instantiation is for a member function, a member class
|
||||
// or a static data member of a class template specialization, the name of
|
||||
// the class template specialization in the qualified-id for the member
|
||||
// name shall be a simple-template-id.
|
||||
//
|
||||
// C++98 has the same restriction, just worded differently.
|
||||
if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
|
||||
Diag(D.getIdentifierLoc(),
|
||||
diag::err_explicit_instantiation_without_qualified_id)
|
||||
<< Prev << D.getCXXScopeSpec().getRange();
|
||||
|
||||
// Check the scope of this explicit instantiation.
|
||||
CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
|
||||
|
||||
// Instantiate static data member.
|
||||
// FIXME: Check for prior specializations and such.
|
||||
Prev->setTemplateSpecializationKind(TSK);
|
||||
@ -3798,6 +3885,29 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
break;
|
||||
}
|
||||
|
||||
// Check the scope of this explicit instantiation.
|
||||
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the explicit instantiation is for a member function, a member class
|
||||
// or a static data member of a class template specialization, the name of
|
||||
// the class template specialization in the qualified-id for the member
|
||||
// name shall be a simple-template-id.
|
||||
//
|
||||
// C++98 has the same restriction, just worded differently.
|
||||
if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&
|
||||
D.getCXXScopeSpec().isSet() &&
|
||||
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
|
||||
Diag(D.getIdentifierLoc(),
|
||||
diag::err_explicit_instantiation_without_qualified_id)
|
||||
<< Specialization << D.getCXXScopeSpec().getRange();
|
||||
|
||||
CheckExplicitInstantiationScope(*this,
|
||||
FunTmpl? (NamedDecl *)FunTmpl
|
||||
: Specialization->getInstantiatedFromMemberFunction(),
|
||||
D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec().isSet());
|
||||
|
||||
// FIXME: Create some kind of ExplicitInstantiationDecl here.
|
||||
return DeclPtrTy();
|
||||
}
|
||||
|
@ -808,9 +808,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
|
||||
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
|
||||
0);
|
||||
|
||||
if (Instantiation->isInvalidDecl())
|
||||
Invalid = true;
|
||||
|
||||
// Add any implicitly-declared members that we might need.
|
||||
AddImplicitlyDeclaredMembersToClass(Instantiation);
|
||||
if (!Invalid)
|
||||
AddImplicitlyDeclaredMembersToClass(Instantiation);
|
||||
|
||||
// Exit the scope of this instantiation.
|
||||
CurContext = PreviousContext;
|
||||
|
@ -246,8 +246,10 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
|
||||
D->getTypeSpecStartLoc(),
|
||||
D->getAccess(),
|
||||
0);
|
||||
if (!Field)
|
||||
if (!Field) {
|
||||
cast<Decl>(Owner)->setInvalidDecl();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Invalid)
|
||||
Field->setInvalidDecl();
|
||||
@ -1189,14 +1191,14 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
}
|
||||
|
||||
// Never instantiate an explicit specialization.
|
||||
if (Def->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
// C++0x [temp.explicit]p9:
|
||||
// Except for inline functions, other explicit instantiation declarations
|
||||
// have the effect of suppressing the implicit instantiation of the entity
|
||||
// to which they refer.
|
||||
if (Def->getTemplateSpecializationKind()
|
||||
if (Var->getTemplateSpecializationKind()
|
||||
== TSK_ExplicitInstantiationDeclaration)
|
||||
return;
|
||||
|
||||
@ -1216,12 +1218,14 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
DeclContext *PreviousContext = CurContext;
|
||||
CurContext = Var->getDeclContext();
|
||||
|
||||
VarDecl *OldVar = Var;
|
||||
Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
|
||||
getTemplateInstantiationArgs(Var)));
|
||||
|
||||
CurContext = PreviousContext;
|
||||
|
||||
if (Var) {
|
||||
Var->setPreviousDeclaration(OldVar);
|
||||
Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind());
|
||||
DeclGroupRef DG(Var);
|
||||
Consumer.HandleTopLevelDecl(DG);
|
||||
}
|
||||
|
@ -1333,6 +1333,9 @@ Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
|
||||
|
||||
for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
|
||||
assert(!CurrTL.isNull());
|
||||
|
||||
// Don't bother recording source locations for qualifiers.
|
||||
CurrTL = CurrTL.getUnqualifiedLoc();
|
||||
|
||||
DeclaratorChunk &DeclType = D.getTypeObject(i);
|
||||
switch (DeclType.Kind) {
|
||||
|
@ -1,7 +1,13 @@
|
||||
// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
|
||||
// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
|
||||
// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
|
||||
// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
|
||||
// RUN: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
|
||||
// RUN: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s &&
|
||||
// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
|
||||
// RUN: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
|
||||
|
||||
// ==-- FIXME: -analyzer-store=basic fails on this file (false negatives). --==
|
||||
// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
|
||||
// NOTWORK: clang-cc -triple i386-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
|
||||
// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
|
||||
// NOTWORK: clang-cc -DTEST_64 -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// The following code is reduced using delta-debugging from
|
||||
@ -12,7 +18,18 @@
|
||||
// both svelte and portable to non-Mac platforms.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef TEST_64
|
||||
typedef long long int64_t;
|
||||
_Bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
|
||||
#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap64Barrier
|
||||
typedef int64_t intptr_t;
|
||||
#else
|
||||
typedef int int32_t;
|
||||
_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
|
||||
#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap32Barrier
|
||||
typedef int32_t intptr_t;
|
||||
#endif
|
||||
|
||||
typedef const void * CFTypeRef;
|
||||
typedef const struct __CFString * CFStringRef;
|
||||
typedef const struct __CFAllocator * CFAllocatorRef;
|
||||
@ -263,7 +280,6 @@ id testSharedClassFromFunction() {
|
||||
|
||||
// Test OSCompareAndSwap
|
||||
_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
|
||||
_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
|
||||
extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
|
||||
|
||||
void testOSCompareAndSwap() {
|
||||
@ -275,20 +291,29 @@ void testOSCompareAndSwap() {
|
||||
[old release];
|
||||
}
|
||||
|
||||
void testOSCompareAndSwap32Barrier() {
|
||||
void testOSCompareAndSwapXXBarrier() {
|
||||
NSString *old = 0;
|
||||
NSString *s = [[NSString alloc] init]; // no-warning
|
||||
if (!OSAtomicCompareAndSwap32Barrier((int32_t) 0, (int32_t) s, (int32_t*) &old))
|
||||
if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) &old))
|
||||
[s release];
|
||||
else
|
||||
[old release];
|
||||
}
|
||||
|
||||
int testOSCompareAndSwap32Barrier_id(Class myclass, id xclass) {
|
||||
if (OSAtomicCompareAndSwap32Barrier(0, (int32_t) myclass, (int32_t*) &xclass))
|
||||
void testOSCompareAndSwapXXBarrier_positive() {
|
||||
NSString *old = 0;
|
||||
NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
|
||||
if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) &old))
|
||||
return;
|
||||
else
|
||||
[old release];
|
||||
}
|
||||
|
||||
int testOSCompareAndSwapXXBarrier_id(Class myclass, id xclass) {
|
||||
if (COMPARE_SWAP_BARRIER(0, (intptr_t) myclass, (intptr_t*) &xclass))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void test_objc_atomicCompareAndSwap() {
|
||||
NSString *old = 0;
|
||||
@ -299,6 +324,16 @@ void test_objc_atomicCompareAndSwap() {
|
||||
[old release];
|
||||
}
|
||||
|
||||
void test_objc_atomicCompareAndSwap_positive() {
|
||||
NSString *old = 0;
|
||||
NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
|
||||
if (!objc_atomicCompareAndSwapPtr(0, s, &old))
|
||||
return;
|
||||
else
|
||||
[old release];
|
||||
}
|
||||
|
||||
|
||||
// Test stringWithFormat (<rdar://problem/6815234>)
|
||||
void test_stringWithFormat() {
|
||||
NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain];
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void test(long double a, int b) {
|
||||
printf("%Lf**%d: %08x %08x %016Lx\n",
|
||||
|
@ -2,7 +2,6 @@
|
||||
// RUN: not grep __builtin %t
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
void p(char *str, int x) {
|
||||
printf("%s: %d\n", str, x);
|
||||
@ -118,7 +117,7 @@ int main() {
|
||||
|
||||
|
||||
|
||||
void strcat() {}
|
||||
char *strcat(char *a, char const *b) {}
|
||||
|
||||
void foo() {
|
||||
__builtin_strcat(0, 0);
|
||||
|
@ -1,6 +1,6 @@
|
||||
// RUN: clang-cc -triple i386-pc-linux-gnu -verify -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
#include <stdint.h>
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
|
||||
// Brace-enclosed string array initializers
|
||||
char a[] = { "asdf" };
|
||||
|
@ -25,8 +25,6 @@ int main() { return 0; }
|
||||
|
||||
#define I 1.0iF
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
volatile double __complex__ accum;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: clang-cc -verify -emit-llvm -o %t %s
|
||||
// RUN: clang-cc -verify -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
void t1() {
|
||||
extern int& a;
|
||||
@ -100,3 +100,10 @@ void f(A* a) {
|
||||
void *foo = 0;
|
||||
void * const & kFoo = foo;
|
||||
|
||||
struct D : C { D(); ~D(); };
|
||||
|
||||
void h() {
|
||||
// CHECK: call void @_ZN1DD1Ev
|
||||
const C& c = D();
|
||||
}
|
||||
|
||||
|
@ -930,6 +930,124 @@ struct test15_D : test15_NV1, virtual test15_B2 {
|
||||
// CHECK-LP32-NEXT: .long __ZN8test15_B4foo3Ev
|
||||
|
||||
|
||||
struct test16_NV1 {
|
||||
virtual void fooNV1() { }
|
||||
virtual void foo_NV1() { }
|
||||
int i;
|
||||
};
|
||||
|
||||
struct test16_NV2 {
|
||||
virtual test16_NV2* foo1() { return 0; }
|
||||
virtual void foo_NV2() { }
|
||||
virtual void foo_NV2b() { }
|
||||
int i;
|
||||
};
|
||||
|
||||
struct test16_B : public test16_NV1, test16_NV2 {
|
||||
virtual test16_B *foo1() { return 0; }
|
||||
virtual test16_B *foo2() { return 0; }
|
||||
virtual test16_B *foo3() { return 0; }
|
||||
virtual void foo_B() { }
|
||||
int i;
|
||||
};
|
||||
|
||||
struct test16_B2 : test16_NV1, virtual test16_B {
|
||||
virtual test16_B2 *foo1() { return 0; }
|
||||
virtual test16_B2 *foo2() { return 0; }
|
||||
virtual void foo_B2() { }
|
||||
int i;
|
||||
};
|
||||
|
||||
struct test16_D : test16_NV1, virtual test16_B2 {
|
||||
virtual test16_D *foo1() { return 0; }
|
||||
};
|
||||
|
||||
// CHECK-LP64: __ZTV8test16_D:
|
||||
// CHECK-LP64-NEXT: .quad 32
|
||||
// CHECK-LP64-NEXT: .quad 16
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN8test16_D4foo1Ev
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .quad 18446744073709551600
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .quad 16
|
||||
// CHECK-LP64-NEXT: .quad 18446744073709551600
|
||||
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZTcv0_n48_v0_n24_N8test16_D4foo1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN9test16_B24foo2Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN9test16_B26foo_B2Ev
|
||||
// CHECK-LP64-NEXT .quad 16
|
||||
// CHECK-LP64-NEXT .quad 16
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64: .quad 18446744073709551600
|
||||
// CHECK-LP64: .quad 18446744073709551584
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
// CHECK-LP64-NEXT: .quad 18446744073709551584
|
||||
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZTcv0_n40_v0_n32_N8test16_D4foo1Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZTcv0_n48_v0_n24_N9test16_B24foo2Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN8test16_B4foo3Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN8test16_B5foo_BEv
|
||||
// CHECK-LP64-NEXT: .quad 18446744073709551568
|
||||
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
|
||||
// CHECK-LP64-NEXT .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev
|
||||
// CHECK-LP64: .quad __ZN10test16_NV27foo_NV2Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN10test16_NV28foo_NV2bEv
|
||||
|
||||
// CHECK-LP32: __ZTV8test16_D:
|
||||
// CHECK-LP32-NEXT: .long 20
|
||||
// CHECK-LP32-NEXT: .long 8
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .long __ZTI8test16_D
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN8test16_D4foo1Ev
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .long 4294967288
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .long 12
|
||||
// CHECK-LP32-NEXT: .long 4294967288
|
||||
// CHECK-LP32-NEXT: .long __ZTI8test16_D
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZTcv0_n24_v0_n12_N8test16_D4foo1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN9test16_B24foo2Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN9test16_B26foo_B2Ev
|
||||
// CHECK-LP32-NEXT .long 8
|
||||
// CHECK-LP32-NEXT .long 8
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32: .long 4294967284
|
||||
// CHECK-LP32-NEXT: .long 4294967276
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .space 4
|
||||
// CHECK-LP32-NEXT: .long 4294967276
|
||||
// CHECK-LP32-NEXT: .long __ZTI8test16_D
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZTcv0_n20_v0_n16_N8test16_D4foo1Ev
|
||||
// CHECK-LP32-NEXT: .long __ZTcv0_n24_v0_n12_N9test16_B24foo2Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN8test16_B4foo3Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN8test16_B5foo_BEv
|
||||
// CHECK-LP32-NEXT: .long 4294967268
|
||||
// CHECK-LP32-NEXT: .long __ZTI8test16_D
|
||||
// CHECK-LP32-NEXT .long __ZTcvn8_n20_v8_n16_N8test16_D4foo1Ev
|
||||
// CHECK-LP32: .long __ZN10test16_NV27foo_NV2Ev
|
||||
// CHECK-LP32-NEXT: .long __ZN10test16_NV28foo_NV2bEv
|
||||
|
||||
|
||||
// CHECK-LP64: __ZTV1B:
|
||||
// CHECK-LP64-NEXT: .space 8
|
||||
@ -1009,6 +1127,7 @@ struct test15_D : test15_NV1, virtual test15_B2 {
|
||||
// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev
|
||||
// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev
|
||||
|
||||
test16_D d16;
|
||||
test15_D d15;
|
||||
test13_D d13;
|
||||
test11_D d11;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
struct A; // expected-note 13 {{forward declaration of 'struct A'}}
|
||||
struct A; // expected-note 14 {{forward declaration of 'struct A'}}
|
||||
|
||||
A f(); // expected-note {{note: 'f' declared here}}
|
||||
|
||||
@ -35,4 +35,8 @@ void g() {
|
||||
b[0]; // expected-error {{calling 'operator[]' with incomplete return type 'struct A'}}
|
||||
b + 1; // expected-error {{calling 'operator+' with incomplete return type 'struct A'}}
|
||||
b->f(); // expected-error {{calling 'operator->' with incomplete return type 'struct A'}}
|
||||
|
||||
A (B::*mfp)() = 0;
|
||||
(b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}}
|
||||
|
||||
}
|
||||
|
@ -14,19 +14,22 @@ struct X0 {
|
||||
T f0(T x) {
|
||||
return x + 1; // expected-error{{invalid operands}}
|
||||
}
|
||||
T* f0(T*, T*);
|
||||
T* f0(T*, T*) { return T(); }
|
||||
|
||||
template<typename U>
|
||||
T f0(T, U);
|
||||
T f0(T, U) { return T(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T X0<T>::value; // expected-error{{no matching constructor}}
|
||||
|
||||
template int X0<int>::value;
|
||||
|
||||
struct NotDefaultConstructible {
|
||||
NotDefaultConstructible(int);
|
||||
};
|
||||
|
||||
template NotDefaultConstructible X0<NotDefaultConstructible>::value;
|
||||
template NotDefaultConstructible X0<NotDefaultConstructible>::value; // expected-note{{instantiation}}
|
||||
|
||||
template int X0<int>::f0(int);
|
||||
template int* X0<int>::f0(int*, int*);
|
||||
@ -43,11 +46,11 @@ template MemPtr X0<MemPtr>::f0(MemPtr); // expected-note{{requested here}}
|
||||
struct X2 {
|
||||
int f0(int); // expected-note{{refers here}}
|
||||
|
||||
template<typename T> T f1(T);
|
||||
template<typename T> T* f1(T*);
|
||||
template<typename T> T f1(T) { return T(); }
|
||||
template<typename T> T* f1(T*) { return 0; }
|
||||
|
||||
template<typename T, typename U> void f2(T, U*); // expected-note{{candidate}}
|
||||
template<typename T, typename U> void f2(T*, U); // expected-note{{candidate}}
|
||||
template<typename T, typename U> void f2(T, U*) { } // expected-note{{candidate}}
|
||||
template<typename T, typename U> void f2(T*, U) { } // expected-note{{candidate}}
|
||||
};
|
||||
|
||||
template int X2::f0(int); // expected-error{{not an instantiation}}
|
||||
@ -57,12 +60,12 @@ template int *X2::f1(int *); // okay
|
||||
template void X2::f2(int *, int *); // expected-error{{ambiguous}}
|
||||
|
||||
|
||||
template<typename T> void print_type();
|
||||
template<typename T> void print_type() { }
|
||||
|
||||
template void print_type<int>();
|
||||
template void print_type<float>();
|
||||
|
||||
template<typename T> void print_type(T*);
|
||||
template<typename T> void print_type(T*) { }
|
||||
|
||||
template void print_type(int*);
|
||||
template void print_type<int>(float*); // expected-error{{does not refer}}
|
||||
|
@ -15,7 +15,6 @@ template class N::X1<int>;
|
||||
template class ::N::X1<int, float>;
|
||||
|
||||
using namespace N;
|
||||
template class X1<float>;
|
||||
|
||||
// Check for some bogus syntax that probably means that the user
|
||||
// wanted to write an explicit specialization, but forgot the '<>'
|
||||
|
@ -122,11 +122,6 @@
|
||||
<p>Pro's of Elsa vs clang:</p>
|
||||
|
||||
<ul>
|
||||
<li>Elsa's support for C++ is far beyond what clang provides. If you need
|
||||
C++ support in the next year, Elsa is a great way to get it. That said,
|
||||
Elsa is missing important support for templates and other pieces: for
|
||||
example, it is not capable of compiling the GCC STL headers from any
|
||||
version newer than GCC 3.4.</li>
|
||||
<li>Elsa's parser and AST is designed to be easily extensible by adding
|
||||
grammar rules. Clang has a very simple and easily hackable parser,
|
||||
but requires you to write C++ code to do it.</li>
|
||||
|
Loading…
Reference in New Issue
Block a user