diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-15 07:44:25 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-15 07:44:25 +0000 |
commit | 98781354c33bdc945ab6ea8c410d36c664ce1f5e (patch) | |
tree | badd8f913c2a7db8d5fbe7d83c862e35e403fd41 | |
parent | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (diff) |
Notes
33 files changed, 999 insertions, 588 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 63f909146e92..106d568c9b24 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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 @@ public: /// \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. diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 7c326dee338c..f21541c3e710 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -584,19 +584,23 @@ public: 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. diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index a6184375e095..3735eee47629 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -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 @@ public: 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 @@ public: static bool classof(const TypeLoc *TL) { return true; } }; +/// \brief Wrapper of type source information for a type with +/// no direct quqlaifiers. +class UnqualTypeLoc : public TypeLoc { +public: + 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 TypeLoc { +class TypeSpecLoc : public UnqualTypeLoc { public: - 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 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 @@ public: 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 @@ public: /// \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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: /// \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 @@ public: 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(); } }; } diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index 107ea85479f9..ecf7cc5c2995 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -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 diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index df386cab6f42..a96757f123e8 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -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) { + if (isa<QualifiedLoc>(TyLoc)) + return static_cast<ImplClass*>(this)-> + VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc)); + + return Visit(cast<UnqualTypeLoc>(TyLoc)); + } + + RetTy Visit(UnqualTypeLoc TyLoc) { TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc); - return TD.Visit(TyLoc.getSourceType().getTypePtr()); + return TD.Visit(TyLoc.getSourceTypePtr()); } -#define TYPELOC(CLASS, PARENT, TYPE) RetTy Visit##CLASS(CLASS TyLoc) { \ - DISPATCH(PARENT); \ -} +#define TYPELOC(CLASS, PARENT) \ + RetTy Visit##CLASS(CLASS TyLoc) { \ + DISPATCH(PARENT); \ + } #include "clang/AST/TypeLocNodes.def" RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b03676d877e2..b1222a3f84eb 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 85b4fd6d6cc0..e028186d46e5 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 429729ea3b0e..da7959b16f9f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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; diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index c24477ae81c5..04e708370af3 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -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 @@ public: } /// \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 @@ public: } -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 @@ public: assert(0 && "A declarator loc wrapper was not handled!"); return TypeSpecLoc(); } + + TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) { + return Visit(TyLoc.getUnqualifiedLoc()); + } }; } @@ -190,7 +190,7 @@ public: } -bool DeclaratorLoc::classof(const TypeLoc *TL) { +bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) { return DeclaratorLocChecker().Visit(*TL); } @@ -208,163 +208,8 @@ public: } -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)); } + diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 9b6125705d9a..eb1265dda7ea 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -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 diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 3844d6a6149c..9456ab64542c 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -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()) diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2834dfeb780a..01a057f67455 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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()) { diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 41f7eefbe82b..6e73db359af1 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -56,6 +56,8 @@ private: 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 @@ public: : 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 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ public: // 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) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 36ad7f514ec8..4763b7fc1ee2 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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); diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 353a6464b18d..b6732561dff0 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -162,7 +162,7 @@ public: : 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 @@ public: } +void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) { + // nothing to do +} void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 4527bb1f9010..ef7c5ec4b1a6 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -160,7 +160,7 @@ public: : 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 @@ public: } +void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) { + // nothing to do here +} void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { Writer.AddSourceLocation(TyLoc.getStartLoc(), Record); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index acb2a6777028..419c8a13c2d4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d8e49c7d6941..a946500660e8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d56b4e114e74..ab0bbe081dbf 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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) { @@ -3574,25 +3626,29 @@ Sema::ActOnExplicitInstantiation(Scope *S, } // C++0x [temp.explicit]p2: - // [...] An explicit instantiation shall appear in an enclosing - // namespace of its template. [...] + // If the explicit instantiation is for a class or member class, the + // elaborated-type-specifier in the declaration shall include a + // simple-template-id. // - // 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); - } - } - + // 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. + 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(); } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 65260c8e1e63..24b83704eba9 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 33fa28866e52..060cc559833f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3cdf6154232b..9603ca8a51c4 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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) { diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index 0ba3cda6d580..a360075645f8 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -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]; diff --git a/test/CodeGen/builtins-powi.c b/test/CodeGen/builtins-powi.c index 5b413a889502..57fa81a3ad12 100644 --- a/test/CodeGen/builtins-powi.c +++ b/test/CodeGen/builtins-powi.c @@ -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", diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 165db9c26753..ac59b274958a 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -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); diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c index 29e9c5561527..e25da9c6eba0 100644 --- a/test/CodeGen/const-init.c +++ b/test/CodeGen/const-init.c @@ -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" }; diff --git a/test/CodeGen/mandel.c b/test/CodeGen/mandel.c index 6f46ee407f5c..27993f0559e9 100644 --- a/test/CodeGen/mandel.c +++ b/test/CodeGen/mandel.c @@ -25,8 +25,6 @@ int main() { return 0; } #define I 1.0iF -#include <math.h> - #include <stdio.h> volatile double __complex__ accum; diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index c235521d43b1..32d46b3e104b 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -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(); +} + diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 9ae81e5d3f33..21fecac11e7b 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -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; diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp index 6134189f0a9a..08bfdefd6247 100644 --- a/test/SemaCXX/incomplete-call.cpp +++ b/test/SemaCXX/incomplete-call.cpp @@ -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'}} + } diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp index b9a4ad282b9f..b04639f6e78c 100644 --- a/test/SemaTemplate/explicit-instantiation.cpp +++ b/test/SemaTemplate/explicit-instantiation.cpp @@ -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}} diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp index 0292964a1a76..9c824d6f4145 100644 --- a/test/SemaTemplate/temp_explicit.cpp +++ b/test/SemaTemplate/temp_explicit.cpp @@ -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 '<>' diff --git a/www/comparison.html b/www/comparison.html index bba2a65d36e6..f0d00bb497be 100644 --- a/www/comparison.html +++ b/www/comparison.html @@ -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> |