summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--include/clang/AST/Decl.h10
-rw-r--r--include/clang/AST/TypeLoc.h525
-rw-r--r--include/clang/AST/TypeLocNodes.def16
-rw-r--r--include/clang/AST/TypeLocVisitor.h25
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td28
-rw-r--r--lib/AST/ASTContext.cpp4
-rw-r--r--lib/AST/Decl.cpp23
-rw-r--r--lib/AST/TypeLoc.cpp213
-rw-r--r--lib/Analysis/CFRefCount.cpp4
-rw-r--r--lib/Analysis/RegionStore.cpp22
-rw-r--r--lib/CodeGen/CGExpr.cpp48
-rw-r--r--lib/CodeGen/CGVtable.cpp96
-rw-r--r--lib/CodeGen/CodeGenModule.cpp47
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp5
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp5
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp17
-rw-r--r--lib/Sema/SemaTemplate.cpp246
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp7
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp12
-rw-r--r--lib/Sema/SemaType.cpp3
-rw-r--r--test/Analysis/NSString.m55
-rw-r--r--test/CodeGen/builtins-powi.c1
-rw-r--r--test/CodeGen/builtins.c3
-rw-r--r--test/CodeGen/const-init.c2
-rw-r--r--test/CodeGen/mandel.c2
-rw-r--r--test/CodeGenCXX/references.cpp9
-rw-r--r--test/CodeGenCXX/virt.cpp119
-rw-r--r--test/SemaCXX/incomplete-call.cpp6
-rw-r--r--test/SemaTemplate/explicit-instantiation.cpp21
-rw-r--r--test/SemaTemplate/temp_explicit.cpp1
-rw-r--r--www/comparison.html5
33 files changed, 999 insertions, 588 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 63f9091..106d568 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 7c326de..f21541c 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 a618437..3735eee 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 107ea85..ecf7cc5 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 df386ca..a96757f 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 b03676d..b1222a3 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 85b4fd6..e028186 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 429729e..da7959b 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 c24477a..04e7083 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 9b61257..eb1265d 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 3844d6a..9456ab6 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 2834dfe..01a057f 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 41f7eef..6e73db3 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 36ad7f5..4763b7f 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 353a646..b673256 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 4527bb1..ef7c5ec 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 acb2a67..419c8a1 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 d8e49c7..a946500 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 d56b4e1..ab0bbe0 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 65260c8..24b8370 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 33fa288..060cc55 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 3cdf615..9603ca8 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 0ba3cda..a360075 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 5b413a8..57fa81a 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 165db9c..ac59b27 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 29e9c55..e25da9c 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 6f46ee4..27993f0 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 c235521..32d46b3 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 9ae81e5..21fecac 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 6134189..08bfdef 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 b9a4ad2..b04639f 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 0292964..9c824d6 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 bba2a65..f0d00bb 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>
OpenPOWER on IntegriCloud