aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/AST
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /include/clang/AST
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
downloadsrc-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz
src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip
Update clang to r84119.vendor/clang/clang-r84119
Notes
Notes: svn path=/vendor/clang/dist/; revision=198092 svn path=/vendor/clang/clang-84119/; revision=198093; tag=vendor/clang/clang-r84119
Diffstat (limited to 'include/clang/AST')
-rw-r--r--include/clang/AST/APValue.h97
-rw-r--r--include/clang/AST/ASTConsumer.h12
-rw-r--r--include/clang/AST/ASTContext.h575
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/Attr.h130
-rw-r--r--include/clang/AST/CXXInheritance.h212
-rw-r--r--include/clang/AST/CanonicalType.h721
-rw-r--r--include/clang/AST/Decl.h765
-rw-r--r--include/clang/AST/DeclBase.h272
-rw-r--r--include/clang/AST/DeclCXX.h1089
-rw-r--r--include/clang/AST/DeclContextInternals.h30
-rw-r--r--include/clang/AST/DeclGroup.h38
-rw-r--r--include/clang/AST/DeclNodes.def43
-rw-r--r--include/clang/AST/DeclObjC.h570
-rw-r--r--include/clang/AST/DeclTemplate.h724
-rw-r--r--include/clang/AST/DeclarationName.h58
-rw-r--r--include/clang/AST/Expr.h1021
-rw-r--r--include/clang/AST/ExprCXX.h625
-rw-r--r--include/clang/AST/ExprObjC.h286
-rw-r--r--include/clang/AST/ExternalASTSource.h8
-rw-r--r--include/clang/AST/NestedNameSpecifier.h46
-rw-r--r--include/clang/AST/ParentMap.h10
-rw-r--r--include/clang/AST/PrettyPrinter.h26
-rw-r--r--include/clang/AST/RecordLayout.h180
-rw-r--r--include/clang/AST/Redeclarable.h162
-rw-r--r--include/clang/AST/Stmt.h484
-rw-r--r--include/clang/AST/StmtCXX.h5
-rw-r--r--include/clang/AST/StmtGraphTraits.h28
-rw-r--r--include/clang/AST/StmtIterator.h64
-rw-r--r--include/clang/AST/StmtNodes.def14
-rw-r--r--include/clang/AST/StmtObjC.h190
-rw-r--r--include/clang/AST/StmtVisitor.h20
-rw-r--r--include/clang/AST/TemplateName.h70
-rw-r--r--include/clang/AST/Type.h1871
-rw-r--r--include/clang/AST/TypeLoc.h538
-rw-r--r--include/clang/AST/TypeLocNodes.def55
-rw-r--r--include/clang/AST/TypeLocVisitor.h58
-rw-r--r--include/clang/AST/TypeNodes.def23
-rw-r--r--include/clang/AST/TypeOrdering.h6
-rw-r--r--include/clang/AST/TypeVisitor.h12
40 files changed, 8192 insertions, 2948 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index 5d5abfe011d4..94d258d9e4e6 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -37,16 +37,16 @@ public:
};
private:
ValueKind Kind;
-
- struct ComplexAPSInt {
- APSInt Real, Imag;
+
+ struct ComplexAPSInt {
+ APSInt Real, Imag;
ComplexAPSInt() : Real(1), Imag(1) {}
};
struct ComplexAPFloat {
APFloat Real, Imag;
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
-
+
struct LV {
Expr* Base;
uint64_t Offset;
@@ -57,16 +57,17 @@ private:
Vec() : Elts(0), NumElts(0) {}
~Vec() { delete[] Elts; }
};
-
+
enum {
- MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
+ MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
};
-
- /// Data - space for the largest member in units of void*. This is an effort
- /// to ensure that the APSInt/APFloat values have proper alignment.
- void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)];
-
+
+ union {
+ void *Aligner;
+ char Data[MaxSize];
+ };
+
public:
APValue() : Kind(Uninitialized) {}
explicit APValue(const APSInt &I) : Kind(Uninitialized) {
@@ -93,7 +94,7 @@ public:
~APValue() {
MakeUninit();
}
-
+
ValueKind getKind() const { return Kind; }
bool isUninit() const { return Kind == Uninitialized; }
bool isInt() const { return Kind == Int; }
@@ -102,54 +103,54 @@ public:
bool isComplexFloat() const { return Kind == ComplexFloat; }
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
-
+
void print(llvm::raw_ostream &OS) const;
void dump() const;
-
+
APSInt &getInt() {
assert(isInt() && "Invalid accessor");
- return *(APSInt*)(void*)Data;
+ return *(APSInt*)(char*)Data;
}
const APSInt &getInt() const {
return const_cast<APValue*>(this)->getInt();
}
-
+
APFloat &getFloat() {
assert(isFloat() && "Invalid accessor");
- return *(APFloat*)(void*)Data;
+ return *(APFloat*)(char*)Data;
}
const APFloat &getFloat() const {
return const_cast<APValue*>(this)->getFloat();
}
-
+
APValue &getVectorElt(unsigned i) const {
assert(isVector() && "Invalid accessor");
- return ((Vec*)(void*)Data)->Elts[i];
+ return ((Vec*)(char*)Data)->Elts[i];
}
unsigned getVectorLength() const {
assert(isVector() && "Invalid accessor");
return ((Vec*)(void *)Data)->NumElts;
}
-
+
APSInt &getComplexIntReal() {
assert(isComplexInt() && "Invalid accessor");
- return ((ComplexAPSInt*)(void*)Data)->Real;
+ return ((ComplexAPSInt*)(char*)Data)->Real;
}
const APSInt &getComplexIntReal() const {
return const_cast<APValue*>(this)->getComplexIntReal();
}
-
+
APSInt &getComplexIntImag() {
assert(isComplexInt() && "Invalid accessor");
- return ((ComplexAPSInt*)(void*)Data)->Imag;
+ return ((ComplexAPSInt*)(char*)Data)->Imag;
}
const APSInt &getComplexIntImag() const {
return const_cast<APValue*>(this)->getComplexIntImag();
}
-
+
APFloat &getComplexFloatReal() {
assert(isComplexFloat() && "Invalid accessor");
- return ((ComplexAPFloat*)(void*)Data)->Real;
+ return ((ComplexAPFloat*)(char*)Data)->Real;
}
const APFloat &getComplexFloatReal() const {
return const_cast<APValue*>(this)->getComplexFloatReal();
@@ -157,7 +158,7 @@ public:
APFloat &getComplexFloatImag() {
assert(isComplexFloat() && "Invalid accessor");
- return ((ComplexAPFloat*)(void*)Data)->Imag;
+ return ((ComplexAPFloat*)(char*)Data)->Imag;
}
const APFloat &getComplexFloatImag() const {
return const_cast<APValue*>(this)->getComplexFloatImag();
@@ -171,44 +172,44 @@ public:
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Offset;
}
-
+
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
- *(APSInt*)(void*)Data = I;
+ *(APSInt*)(char*)Data = I;
}
void setFloat(const APFloat &F) {
assert(isFloat() && "Invalid accessor");
- *(APFloat*)(void*)Data = F;
+ *(APFloat*)(char*)Data = F;
}
void setVector(const APValue *E, unsigned N) {
assert(isVector() && "Invalid accessor");
- ((Vec*)(void*)Data)->Elts = new APValue[N];
- ((Vec*)(void*)Data)->NumElts = N;
+ ((Vec*)(char*)Data)->Elts = new APValue[N];
+ ((Vec*)(char*)Data)->NumElts = N;
for (unsigned i = 0; i != N; ++i)
- ((Vec*)(void*)Data)->Elts[i] = E[i];
+ ((Vec*)(char*)Data)->Elts[i] = E[i];
}
void setComplexInt(const APSInt &R, const APSInt &I) {
- assert(R.getBitWidth() == I.getBitWidth() &&
+ assert(R.getBitWidth() == I.getBitWidth() &&
"Invalid complex int (type mismatch).");
assert(isComplexInt() && "Invalid accessor");
- ((ComplexAPSInt*)(void*)Data)->Real = R;
- ((ComplexAPSInt*)(void*)Data)->Imag = I;
+ ((ComplexAPSInt*)(char*)Data)->Real = R;
+ ((ComplexAPSInt*)(char*)Data)->Imag = I;
}
void setComplexFloat(const APFloat &R, const APFloat &I) {
- assert(&R.getSemantics() == &I.getSemantics() &&
+ assert(&R.getSemantics() == &I.getSemantics() &&
"Invalid complex float (type mismatch).");
assert(isComplexFloat() && "Invalid accessor");
- ((ComplexAPFloat*)(void*)Data)->Real = R;
- ((ComplexAPFloat*)(void*)Data)->Imag = I;
+ ((ComplexAPFloat*)(char*)Data)->Real = R;
+ ((ComplexAPFloat*)(char*)Data)->Imag = I;
}
void setLValue(Expr *B, uint64_t O) {
assert(isLValue() && "Invalid accessor");
- ((LV*)(void*)Data)->Base = B;
- ((LV*)(void*)Data)->Offset = O;
+ ((LV*)(char*)Data)->Base = B;
+ ((LV*)(char*)Data)->Offset = O;
}
-
+
const APValue &operator=(const APValue &RHS);
-
+
private:
void MakeUninit();
void MakeInt() {
@@ -218,27 +219,27 @@ private:
}
void MakeFloat() {
assert(isUninit() && "Bad state change");
- new ((APFloat*)(void*)Data) APFloat(0.0);
+ new ((void*)(char*)Data) APFloat(0.0);
Kind = Float;
}
void MakeVector() {
assert(isUninit() && "Bad state change");
- new ((Vec*)(void*)Data) Vec();
+ new ((void*)(char*)Data) Vec();
Kind = Vector;
}
void MakeComplexInt() {
assert(isUninit() && "Bad state change");
- new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt();
+ new ((void*)(char*)Data) ComplexAPSInt();
Kind = ComplexInt;
}
void MakeComplexFloat() {
assert(isUninit() && "Bad state change");
- new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat();
+ new ((void*)(char*)Data) ComplexAPFloat();
Kind = ComplexFloat;
}
void MakeLValue() {
assert(isUninit() && "Bad state change");
- new ((LV*)(void*)Data) LV();
+ new ((void*)(char*)Data) LV();
Kind = LValue;
}
};
@@ -247,7 +248,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
V.print(OS);
return OS;
}
-
+
} // end namespace clang.
#endif
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 6dc7e13d8f70..af6bf30b6882 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -36,27 +36,27 @@ public:
ASTConsumer() : SemaConsumer(false) { }
virtual ~ASTConsumer() {}
-
+
/// Initialize - This is called to initialize the consumer, providing the
/// ASTContext and the Action.
virtual void Initialize(ASTContext &Context) {}
-
+
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by the parser to process every top-level Decl*. Note that D can
/// be the head of a chain of Decls (e.g. for `int a, b` the chain will have
/// two elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D);
-
+
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
- virtual void HandleTranslationUnit(ASTContext &Ctx) {}
-
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {}
+
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// (e.g. struct, union, enum, class) is completed. This allows the client to
/// hack on the type, which can occur at any point in the file (because these
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
-
+
/// \brief Callback invoked at the end of a translation unit to
/// notify the consumer that the given tentative definition should
/// be completed.
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 041a0f33ad4d..63f909146e92 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -22,6 +22,7 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/OwningPtr.h"
@@ -43,24 +44,26 @@ namespace clang {
class TargetInfo;
// Decls
class Decl;
+ class FieldDecl;
+ class ObjCIvarDecl;
+ class ObjCIvarRefExpr;
class ObjCPropertyDecl;
class RecordDecl;
class TagDecl;
+ class TemplateTypeParmDecl;
class TranslationUnitDecl;
class TypeDecl;
class TypedefDecl;
- class TemplateTypeParmDecl;
- class FieldDecl;
- class ObjCIvarRefExpr;
- class ObjCIvarDecl;
-
+ class UnresolvedUsingDecl;
+ class UsingDecl;
+
namespace Builtin { class Context; }
-
+
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
-class ASTContext {
+class ASTContext {
std::vector<Type*> Types;
- llvm::FoldingSet<ExtQualType> ExtQualTypes;
+ llvm::FoldingSet<ExtQuals> ExtQualNodes;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
@@ -70,17 +73,21 @@ class ASTContext {
llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
- std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
- std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes;
+ llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
+ llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes;
llvm::FoldingSet<VectorType> VectorTypes;
llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+ llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
+ llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
- llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
+ llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes;
+ llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -97,46 +104,109 @@ class ASTContext {
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
+ /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+
llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes;
llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes;
-
+
/// BuiltinVaListType - built-in va list type.
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
QualType BuiltinVaListType;
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
- QualType ObjCIdType;
- const RecordType *IdStructType;
-
+ QualType ObjCIdTypedefType;
+
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelType;
const RecordType *SelStructType;
-
+
/// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
QualType ObjCProtoType;
const RecordType *ProtoStructType;
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
- QualType ObjCClassType;
- const RecordType *ClassStructType;
-
+ QualType ObjCClassTypedefType;
+
QualType ObjCConstantStringType;
RecordDecl *CFConstantStringTypeDecl;
RecordDecl *ObjCFastEnumerationStateTypeDecl;
-
- /// \brief Keeps track of all declaration attributes.
+
+ /// \brief The type for the C FILE type.
+ TypeDecl *FILEDecl;
+
+ /// \brief The type for the C jmp_buf type.
+ TypeDecl *jmp_bufDecl;
+
+ /// \brief The type for the C sigjmp_buf type.
+ TypeDecl *sigjmp_bufDecl;
+
+ /// \brief Keeps track of all declaration attributes.
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class.
llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
-
+
+ /// \brief Keeps track of the static data member templates from which
+ /// static data members of class template specializations were instantiated.
+ ///
+ /// This data structure stores the mapping from instantiations of static
+ /// data members to the static data member representations within the
+ /// class template from which they were instantiated along with the kind
+ /// of instantiation or specialization (a TemplateSpecializationKind - 1).
+ ///
+ /// Given the following example:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// static T value;
+ /// };
+ ///
+ /// template<typename T>
+ /// T X<T>::value = T(17);
+ ///
+ /// int *x = &X<int>::value;
+ /// \endcode
+ ///
+ /// 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 *>
+ InstantiatedFromStaticDataMember;
+
+ /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
+ /// where created during instantiation.
+ ///
+ /// For example:
+ /// \code
+ /// template<typename T>
+ /// struct A {
+ /// void f();
+ /// };
+ ///
+ /// template<typename T>
+ /// struct B : A<T> {
+ /// using A<T>::f;
+ /// };
+ ///
+ /// template struct B<int>;
+ /// \endcode
+ ///
+ /// This mapping will contain an entry that maps from the UsingDecl in
+ /// B<int> to the UnresolvedUsingDecl in B<T>.
+ llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>
+ InstantiatedFromUnresolvedUsingDecl;
+
+ llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
+
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
SourceManager &SourceMgr;
-
+
/// LangOpts - The language options used to create the AST associated with
/// this ASTContext object.
LangOptions LangOpts;
@@ -144,17 +214,17 @@ class ASTContext {
/// \brief Whether we have already loaded comment source ranges from an
/// external source.
bool LoadedExternalComments;
-
+
/// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
bool FreeMemory;
llvm::MallocAllocator MallocAlloc;
llvm::BumpPtrAllocator BumpAlloc;
-
+
/// \brief Mapping from declarations to their comments, once we have
/// already looked up the comment associated with a given declaration.
llvm::DenseMap<const Decl *, std::string> DeclComments;
-
-public:
+
+public:
TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
@@ -163,41 +233,73 @@ public:
llvm::OwningPtr<ExternalASTSource> ExternalSource;
clang::PrintingPolicy PrintingPolicy;
+ // Typedefs which may be provided defining the structure of Objective-C
+ // pseudo-builtins
+ QualType ObjCIdRedefinitionType;
+ QualType ObjCClassRedefinitionType;
+
/// \brief Source ranges for all of the comments in the source file,
/// sorted in order of appearance in the translation unit.
std::vector<SourceRange> Comments;
-
+
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) {
return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
BumpAlloc.Allocate(Size, Align);
}
- void Deallocate(void *Ptr) {
+ void Deallocate(void *Ptr) {
if (FreeMemory)
- MallocAlloc.Deallocate(Ptr);
+ MallocAlloc.Deallocate(Ptr);
}
const LangOptions& getLangOptions() const { return LangOpts; }
-
- FullSourceLoc getFullLoc(SourceLocation Loc) const {
+
+ FullSourceLoc getFullLoc(SourceLocation Loc) const {
return FullSourceLoc(Loc,SourceMgr);
}
/// \brief Retrieve the attributes for the given declaration.
Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
-
+
/// \brief Erase the attributes corresponding to the given declaration.
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
-
+
+ /// \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);
+
+ /// \brief Note that the static data member \p Inst is an instantiation of
+ /// the static data member template \p Tmpl of a class template.
+ void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
+ TemplateSpecializationKind TSK);
+
+ /// \brief If this using decl is instantiated from an unresolved using decl,
+ /// return it.
+ UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
+
+ /// \brief Note that the using decl \p Inst is an instantiation of
+ /// the unresolved using decl \p Tmpl of a class template.
+ void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst,
+ UnresolvedUsingDecl *Tmpl);
+
+
+ FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
+
+ void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
+
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
+
const char *getCommentForDecl(const Decl *D);
-
+
// Builtin Types.
QualType VoidTy;
QualType BoolTy;
QualType CharTy;
- QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
+ QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
QualType UnsignedLongLongTy, UnsignedInt128Ty;
@@ -207,6 +309,7 @@ public:
QualType OverloadTy;
QualType DependentTy;
QualType UndeducedAutoTy;
+ QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@@ -232,23 +335,52 @@ public:
//===--------------------------------------------------------------------===//
// Type Constructors
//===--------------------------------------------------------------------===//
-
- /// getAddSpaceQualType - Return the uniqued reference to the type for an
- /// address space qualified type with the specified type and address space.
- /// The resulting type has a union of the qualifiers from T and the address
- /// space. If T already has an address space specifier, it is silently
+
+private:
+ /// getExtQualType - Return a type with extended qualifiers.
+ QualType getExtQualType(const Type *Base, Qualifiers Quals);
+
+public:
+ /// getAddSpaceQualType - Return the uniqued reference to the type for an
+ /// address space qualified type with the specified type and address space.
+ /// The resulting type has a union of the qualifiers from T and the address
+ /// space. If T already has an address space specifier, it is silently
/// replaced.
QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace);
-
+
/// getObjCGCQualType - Returns the uniqued reference to the type for an
/// objc gc qualified type. The retulting type has a union of the qualifiers
/// from T and the gc attribute.
- QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr);
-
+ QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr);
+
+ /// getRestrictType - Returns the uniqued reference to the type for a
+ /// 'restrict' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'restrict'.
+ QualType getRestrictType(QualType T) {
+ return T.withFastQualifiers(Qualifiers::Restrict);
+ }
+
+ /// getVolatileType - Returns the uniqued reference to the type for a
+ /// 'volatile' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'volatile'.
+ QualType getVolatileType(QualType T);
+
+ /// getConstType - Returns the uniqued reference to the type for a
+ /// 'const' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'const'.
+ ///
+ /// It can be reasonably expected that this will always be
+ /// equivalent to calling T.withConst().
+ QualType getConstType(QualType T) { return T.withConst(); }
+
+ /// getNoReturnType - Add the noreturn attribute to the given type which must
+ /// be a FunctionType or a pointer to an allowable type or a BlockPointer.
+ QualType getNoReturnType(QualType T);
+
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
-
+
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T);
@@ -274,15 +406,17 @@ public:
/// variable array of the specified element type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals);
-
+ unsigned EltTypeQuals,
+ SourceRange Brackets);
+
/// getDependentSizedArrayType - Returns a non-unique reference to
/// the type for a dependently-sized array of the specified element
/// type. FIXME: We will need these to be uniqued, or at least
/// comparable, at some point.
QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals);
+ unsigned EltTypeQuals,
+ SourceRange Brackets);
/// getIncompleteArrayType - Returns a unique reference to the type for a
/// incomplete array of the specified element type.
@@ -295,7 +429,23 @@ public:
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals);
-
+
+ /// getConstantArrayWithExprType - Return a reference to the type for a
+ /// constant array of the specified element type.
+ QualType getConstantArrayWithExprType(QualType EltTy,
+ const llvm::APInt &ArySize,
+ Expr *ArySizeExpr,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals,
+ SourceRange Brackets);
+
+ /// getConstantArrayWithoutExprType - Return a reference to the type
+ /// for a constant array of the specified element type.
+ QualType getConstantArrayWithoutExprType(QualType EltTy,
+ const llvm::APInt &ArySize,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals);
+
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType getVectorType(QualType VectorType, unsigned NumElts);
@@ -309,13 +459,13 @@ public:
/// the type for a dependently-sized vector of the specified element
/// type. FIXME: We will need these to be uniqued, or at least
/// comparable, at some point.
- QualType getDependentSizedExtVectorType(QualType VectorType,
+ QualType getDependentSizedExtVectorType(QualType VectorType,
Expr *SizeExpr,
SourceLocation AttrLoc);
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
- QualType getFunctionNoProtoType(QualType ResultTy);
+ QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false);
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
@@ -323,7 +473,8 @@ public:
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec = false,
bool hasAnyExceptionSpec = false,
- unsigned NumExs = 0, const QualType *ExArray = 0);
+ unsigned NumExs = 0, const QualType *ExArray = 0,
+ bool NoReturn = false);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
@@ -332,9 +483,8 @@ public:
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
QualType getTypedefType(TypedefDecl *Decl);
- QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
- QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
IdentifierInfo *Name = 0);
@@ -345,37 +495,40 @@ public:
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
QualType NamedType);
- QualType getTypenameType(NestedNameSpecifier *NNS,
+ QualType getTypenameType(NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon = QualType());
- QualType getTypenameType(NestedNameSpecifier *NNS,
+ QualType getTypenameType(NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
+ QualType getElaboratedType(QualType UnderlyingType,
+ ElaboratedType::TagKind Tag);
+
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **Protocols = 0,
+ unsigned NumProtocols = 0);
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the
/// given interface decl and the conforming protocol list.
- QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
+ QualType getObjCObjectPointerType(QualType OIT,
ObjCProtocolDecl **ProtocolList = 0,
unsigned NumProtocols = 0);
-
- /// getObjCQualifiedInterfaceType - Return a
- /// ObjCQualifiedInterfaceType type for the given interface decl and
- /// the conforming protocol list.
- QualType getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **ProtocolList,
- unsigned NumProtocols);
-
+
+ QualType getObjCProtocolListType(QualType T,
+ ObjCProtocolDecl **Protocols,
+ unsigned NumProtocols);
+
/// getTypeOfType - GCC extension.
QualType getTypeOfExprType(Expr *e);
QualType getTypeOfType(QualType t);
-
+
/// getDecltypeType - C++0x decltype.
QualType getDecltypeType(Expr *e);
-
+
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
- QualType getTagDeclType(TagDecl *Decl);
-
+ QualType getTagDeclType(const TagDecl *Decl);
+
/// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
/// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
QualType getSizeType() const;
@@ -392,15 +545,15 @@ public:
/// getUnsignedWCharType - Return the type of "unsigned wchar_t".
/// Used when in C++, as a GCC extension.
QualType getUnsignedWCharType() const;
-
+
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
-
+
// getCFConstantStringType - Return the C structure type used to represent
// constant CFStrings.
- QualType getCFConstantStringType();
-
+ QualType getCFConstantStringType();
+
/// Get the structure type used to representation CFStrings, or NULL
/// if it hasn't yet been built.
QualType getRawCFConstantStringType() {
@@ -412,13 +565,13 @@ public:
// This setter/getter represents the ObjC type for an NSConstantString.
void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl);
- QualType getObjCConstantStringInterface() const {
- return ObjCConstantStringType;
+ QualType getObjCConstantStringInterface() const {
+ return ObjCConstantStringType;
}
//// This gets the struct used to keep track of fast enumerations.
QualType getObjCFastEnumerationStateType();
-
+
/// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
/// been built.
QualType getRawObjCFastEnumerationStateType() {
@@ -429,109 +582,166 @@ public:
void setObjCFastEnumerationStateType(QualType T);
+ /// \brief Set the type for the C FILE type.
+ void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
+
+ /// \brief Retrieve the C FILE type.
+ QualType getFILEType() {
+ if (FILEDecl)
+ return getTypeDeclType(FILEDecl);
+ return QualType();
+ }
+
+ /// \brief Set the type for the C jmp_buf type.
+ void setjmp_bufDecl(TypeDecl *jmp_bufDecl) {
+ this->jmp_bufDecl = jmp_bufDecl;
+ }
+
+ /// \brief Retrieve the C jmp_buf type.
+ QualType getjmp_bufType() {
+ if (jmp_bufDecl)
+ return getTypeDeclType(jmp_bufDecl);
+ return QualType();
+ }
+
+ /// \brief Set the type for the C sigjmp_buf type.
+ void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) {
+ this->sigjmp_bufDecl = sigjmp_bufDecl;
+ }
+
+ /// \brief Retrieve the C sigjmp_buf type.
+ QualType getsigjmp_bufType() {
+ if (sigjmp_bufDecl)
+ return getTypeDeclType(sigjmp_bufDecl);
+ return QualType();
+ }
+
/// getObjCEncodingForType - Emit the ObjC type encoding for the
/// given type into \arg S. If \arg NameFields is specified then
/// record field names are also encoded.
- void getObjCEncodingForType(QualType t, std::string &S,
+ void getObjCEncodingForType(QualType t, std::string &S,
const FieldDecl *Field=0);
void getLegacyIntegralTypeEncoding(QualType &t) const;
-
+
// Put the string version of type qualifiers into S.
- void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
+ void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
std::string &S) const;
-
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
-
+
/// getObjCEncodingForPropertyDecl - Return the encoded type for
/// this method declaration. If non-NULL, Container must be either
/// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
/// only be NULL when getting encodings for protocol properties.
- void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
const Decl *Container,
std::string &S);
-
+
+ bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+ ObjCProtocolDecl *rProto);
+
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
- QualType getObjCIdType() const { return ObjCIdType; }
+ QualType getObjCIdType() const { return ObjCIdTypedefType; }
void setObjCIdType(QualType T);
-
+
void setObjCSelType(QualType T);
QualType getObjCSelType() const { return ObjCSelType; }
-
+
void setObjCProtoType(QualType QT);
QualType getObjCProtoType() const { return ObjCProtoType; }
-
+
/// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
/// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
/// struct.
- QualType getObjCClassType() const { return ObjCClassType; }
+ QualType getObjCClassType() const { return ObjCClassTypedefType; }
void setObjCClassType(QualType T);
-
+
void setBuiltinVaListType(QualType T);
QualType getBuiltinVaListType() const { return BuiltinVaListType; }
QualType getFixedWidthIntType(unsigned Width, bool Signed);
- TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ /// getCVRQualifiedType - Returns a type with additional const,
+ /// volatile, or restrict qualifiers.
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) {
+ return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(QualType T, Qualifiers Qs) {
+ if (!Qs.hasNonFastQualifiers())
+ return T.withFastQualifiers(Qs.getFastQualifiers());
+ QualifierCollector Qc(Qs);
+ const Type *Ptr = Qc.strip(T);
+ return getExtQualType(Ptr, Qc);
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(const Type *T, Qualifiers Qs) {
+ if (!Qs.hasNonFastQualifiers())
+ return QualType(T, Qs.getFastQualifiers());
+ return getExtQualType(T, Qs);
+ }
+
+ TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template);
+ TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ bool TemplateKeyword,
+ OverloadedFunctionDecl *Template);
- TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name);
enum GetBuiltinTypeError {
- GE_None, //< No error
- GE_Missing_FILE //< Missing the FILE type from <stdio.h>
+ GE_None, //< No error
+ GE_Missing_stdio, //< Missing a type from <stdio.h>
+ GE_Missing_setjmp //< Missing a type from <setjmp.h>
};
-
+
/// GetBuiltinType - Return the type for the specified builtin.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
-
+
private:
QualType getFromTargetType(unsigned Type) const;
//===--------------------------------------------------------------------===//
// Type Predicates.
//===--------------------------------------------------------------------===//
-
-public:
- /// isObjCObjectPointerType - Returns true if type is an Objective-C pointer
- /// to an object type. This includes "id" and "Class" (two 'special' pointers
- /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
- /// ID type).
- bool isObjCObjectPointerType(QualType Ty) const;
+public:
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
- QualType::GCAttrTypes getObjCGCAttrKind(const QualType &Ty) const;
-
+ Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const;
-
+
//===--------------------------------------------------------------------===//
// Type Sizing and Analysis
//===--------------------------------------------------------------------===//
-
+
/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
/// scalar floating point type.
const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
-
+
/// getTypeInfo - Get the size and alignment of the specified complete type in
/// bits.
std::pair<uint64_t, unsigned> getTypeInfo(const Type *T);
std::pair<uint64_t, unsigned> getTypeInfo(QualType T) {
return getTypeInfo(T.getTypePtr());
}
-
+
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
uint64_t getTypeSize(QualType T) {
@@ -540,7 +750,7 @@ public:
uint64_t getTypeSize(const Type *T) {
return getTypeInfo(T).first;
}
-
+
/// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
/// This method does not work on incomplete types.
unsigned getTypeAlign(QualType T) {
@@ -549,23 +759,23 @@ public:
unsigned getTypeAlign(const Type *T) {
return getTypeInfo(T).second;
}
-
+
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
/// type for the current target in bits. This can be different than the ABI
/// alignment in cases where it is beneficial for performance to overalign
/// a data type.
unsigned getPreferredTypeAlign(const Type *T);
-
+
/// getDeclAlignInBytes - Return the alignment of the specified decl
/// that should be returned by __alignof(). Note that bitfields do
/// not have a valid alignment, so this method will assert on them.
unsigned getDeclAlignInBytes(const Decl *D);
-
+
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D);
-
+
/// getASTObjCInterfaceLayout - Get or compute information about the
/// layout of the specified Objective-C interface.
const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D);
@@ -592,14 +802,14 @@ public:
//===--------------------------------------------------------------------===//
// Type Operators
//===--------------------------------------------------------------------===//
-
+
/// getCanonicalType - Return the canonical (structural) type corresponding to
/// the specified potentially non-canonical type. The non-canonical version
/// of a type may have many "decorated" versions of types. Decorators can
/// include typedefs, 'typeof' operators, etc. The returned type is guaranteed
/// to be free of any of these, allowing two canonical types to be compared
/// for exact equality with a simple pointer comparison.
- QualType getCanonicalType(QualType T);
+ CanQualType getCanonicalType(QualType T);
const Type *getCanonicalType(const Type *T) {
return T->getCanonicalTypeInternal().getTypePtr();
}
@@ -608,7 +818,7 @@ public:
bool hasSameType(QualType T1, QualType T2) {
return getCanonicalType(T1) == getCanonicalType(T2);
}
-
+
/// \brief Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
@@ -617,20 +827,7 @@ public:
return T1.getUnqualifiedType() == T2.getUnqualifiedType();
}
- /// \brief Retrieves the "canonical" declaration of the given declaration.
- Decl *getCanonicalDecl(Decl *D);
-
- /// \brief Retrieves the "canonical" declaration of the given tag
- /// declaration.
- ///
- /// The canonical declaration for the given tag declaration is
- /// either the definition of the tag (if it is a complete type) or
- /// the first declaration of that tag.
- TagDecl *getCanonicalDecl(TagDecl *Tag) {
- return cast<TagDecl>(getCanonicalDecl((Decl *)Tag));
- }
-
- /// \brief Retrieves the "canonical" declaration of
+ /// \brief Retrieves the "canonical" declaration of
/// \brief Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
@@ -678,6 +875,13 @@ public:
/// types, values, and templates.
TemplateName getCanonicalTemplateName(TemplateName Name);
+ /// \brief Retrieve the "canonical" template argument.
+ ///
+ /// The canonical template argument is the simplest template argument
+ /// (which may be a type, value, expression, or declaration) that
+ /// expresses the value of the argument.
+ TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg);
+
/// Type Query functions. If the type is an instance of the specified class,
/// return the Type pointer for the underlying maximally pretty type. This
/// is a member of ASTContext because this may need to do some amount of
@@ -693,10 +897,17 @@ public:
return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
}
- /// getBaseElementType - Returns the innermost element type of a variable
- /// length array type. For example, will return "int" for int[m][n]
- QualType getBaseElementType(const VariableArrayType *VAT);
-
+ /// getBaseElementType - Returns the innermost element type of an array type.
+ /// For example, will return "int" for int[m][n]
+ QualType getBaseElementType(const ArrayType *VAT);
+
+ /// getBaseElementType - Returns the innermost element type of a type
+ /// (which needn't actually be an array type).
+ QualType getBaseElementType(QualType QT);
+
+ /// getConstantArrayElementCount - Returns number of constant array elements.
+ uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
@@ -704,23 +915,35 @@ public:
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType getArrayDecayedType(QualType T);
-
- /// getIntegerTypeOrder - Returns the highest ranked integer type:
+
+ /// getPromotedIntegerType - Returns the type that Promotable will
+ /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
+ /// integer type.
+ QualType getPromotedIntegerType(QualType PromotableType);
+
+ /// \brief Whether this is a promotable bitfield reference according
+ /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
+ ///
+ /// \returns the type this bit-field will promote to, or NULL if no
+ /// promotion occurs.
+ QualType isPromotableBitField(Expr *E);
+
+ /// getIntegerTypeOrder - Returns the highest ranked integer type:
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
- /// LHS < RHS, return -1.
+ /// LHS < RHS, return -1.
int getIntegerTypeOrder(QualType LHS, QualType RHS);
-
+
/// getFloatingTypeOrder - Compare the rank of the two specified floating
/// point types, ignoring the domain of the type (i.e. 'double' ==
/// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If
- /// LHS < RHS, return -1.
+ /// LHS < RHS, return -1.
int getFloatingTypeOrder(QualType LHS, QualType RHS);
- /// getFloatingTypeOfSizeWithinDomain - Returns a real floating
- /// point or a complex type (based on typeDomain/typeSize).
+ /// getFloatingTypeOfSizeWithinDomain - Returns a real floating
+ /// point or a complex type (based on typeDomain/typeSize).
/// 'typeDomain' is a real floating point or complex type.
/// 'typeSize' is a real floating point or complex type.
- QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
+ QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
QualType typeDomain) const;
private:
@@ -732,33 +955,28 @@ public:
//===--------------------------------------------------------------------===//
// Type Compatibility Predicates
//===--------------------------------------------------------------------===//
-
+
/// Compatibility predicates used to check assignment expressions.
bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
-
+
bool isObjCIdType(QualType T) const {
- return T == ObjCIdType;
- }
- bool isObjCIdStructType(QualType T) const {
- if (!IdStructType) // ObjC isn't enabled
- return false;
- return T->getAsStructureType() == IdStructType;
+ return T == ObjCIdTypedefType;
}
bool isObjCClassType(QualType T) const {
- return T == ObjCClassType;
- }
- bool isObjCClassStructType(QualType T) const {
- if (!ClassStructType) // ObjC isn't enabled
- return false;
- return T->getAsStructureType() == ClassStructType;
+ return T == ObjCClassTypedefType;
}
bool isObjCSelType(QualType T) const {
assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
return T->getAsStructureType() == SelStructType;
}
+ bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
+ bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+ bool ForCompare);
// Check the safety of assignment from LHS to RHS
- bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
+ bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+ bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS);
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
@@ -766,6 +984,11 @@ public:
QualType mergeTypes(QualType, QualType);
QualType mergeFunctionTypes(QualType, QualType);
+ /// UsualArithmeticConversionsType - handles the various conversions
+ /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
+ /// and returns the result type of that conversion.
+ QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
+
//===--------------------------------------------------------------------===//
// Integer Predicates
//===--------------------------------------------------------------------===//
@@ -782,15 +1005,15 @@ public:
//===--------------------------------------------------------------------===//
// Type Iterators.
//===--------------------------------------------------------------------===//
-
+
typedef std::vector<Type*>::iterator type_iterator;
typedef std::vector<Type*>::const_iterator const_type_iterator;
-
+
type_iterator types_begin() { return Types.begin(); }
type_iterator types_end() { return Types.end(); }
const_type_iterator types_begin() const { return Types.begin(); }
- const_type_iterator types_end() const { return Types.end(); }
-
+ const_type_iterator types_end() const { return Types.end(); }
+
//===--------------------------------------------------------------------===//
// Integer Values
//===--------------------------------------------------------------------===//
@@ -803,15 +1026,37 @@ public:
return Res;
}
+ /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
+ /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+
+ /// \brief Set the implementation of ObjCInterfaceDecl.
+ void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+ ObjCImplementationDecl *ImplD);
+ /// \brief Set the implementation of ObjCCategoryDecl.
+ void setObjCImplementation(ObjCCategoryDecl *CatD,
+ ObjCCategoryImplDecl *ImplD);
+
+ /// \brief Allocate an uninitialized DeclaratorInfo.
+ ///
+ /// The caller should initialize the memory held by DeclaratorInfo using
+ /// the TypeLoc wrappers.
+ ///
+ /// \param T the type that will be the basis for type source info. This type
+ /// should refer to how the declarator was written in source code, not to
+ /// what type semantic analysis resolved the declarator to.
+ DeclaratorInfo *CreateDeclaratorInfo(QualType T);
+
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
-
+
void InitBuiltinTypes();
void InitBuiltinType(QualType &R, BuiltinType::Kind K);
-
+
// Return the ObjC type encoding for a given type.
- void getObjCEncodingForTypeImpl(QualType t, std::string &S,
+ void getObjCEncodingForTypeImpl(QualType t, std::string &S,
bool ExpandPointedToStructures,
bool ExpandStructures,
const FieldDecl *Field,
@@ -819,7 +1064,7 @@ private:
bool EncodingProperty = false);
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
- const ObjCImplementationDecl *Impl);
+ const ObjCImplementationDecl *Impl);
};
} // end namespace clang
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index e9f150574b05..abd36f7e5f0f 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -13,7 +13,7 @@
#include "clang/Basic/Diagnostic.h"
namespace clang {
- namespace diag {
+ namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
#define ASTSTART
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 7d3009b01129..6a5e3666a92c 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -14,6 +14,9 @@
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
+#include "llvm/Support/Casting.h"
+using llvm::dyn_cast;
+
#include <cassert>
#include <cstring>
#include <string>
@@ -54,22 +57,24 @@ public:
DLLImport,
Deprecated,
Destructor,
- FastCall,
+ FastCall,
Format,
FormatArg,
GNUInline,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
+ Malloc,
+ NoDebug,
+ NoInline,
+ NonNull,
NoReturn,
NoThrow,
- Nodebug,
- Noinline,
- NonNull,
ObjCException,
ObjCNSObject,
CFReturnsRetained, // Clang/Checker-specific.
NSReturnsRetained, // Clang/Checker-specific.
Overloadable, // Clang-specific
Packed,
+ PragmaPack,
Pure,
Regparm,
ReqdWorkGroupSize, // OpenCL-specific
@@ -78,14 +83,14 @@ public:
StdCall,
TransparentUnion,
Unavailable,
- Unused,
+ Unused,
Used,
Visibility,
WarnUnusedResult,
Weak,
WeakImport
};
-
+
private:
Attr *Next;
Kind AttrKind;
@@ -99,16 +104,16 @@ protected:
void operator delete(void* data) throw() {
assert(0 && "Attrs cannot be released with regular 'delete'.");
}
-
+
protected:
Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
virtual ~Attr() {
assert(Next == 0 && "Destroy didn't work");
}
public:
-
+
void Destroy(ASTContext &C);
-
+
/// \brief Whether this attribute should be merged to new
/// declarations.
virtual bool isMerged() const { return true; }
@@ -119,17 +124,24 @@ public:
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
+ template<typename T> const T *getNext() const {
+ for (const Attr *attr = getNext(); attr; attr = attr->getNext())
+ if (const T *V = dyn_cast<T>(attr))
+ return V;
+ return 0;
+ }
+
bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
-
+
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
-
+
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -146,36 +158,39 @@ public: \
static bool classof(const ATTR##Attr *A) { return true; } \
}
-class PackedAttr : public Attr {
+DEF_SIMPLE_ATTR(Packed);
+
+class PragmaPackAttr : public Attr {
unsigned Alignment;
public:
- PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {}
+ PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {}
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
- virtual Attr* clone(ASTContext &C) const {
- return ::new (C) PackedAttr(Alignment);
+ virtual Attr* clone(ASTContext &C) const {
+ return ::new (C) PragmaPackAttr(Alignment);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
- return A->getKind() == Packed;
+ return A->getKind() == PragmaPack;
}
- static bool classof(const PackedAttr *A) { return true; }
+ static bool classof(const PragmaPackAttr *A) { return true; }
};
-
+
class AlignedAttr : public Attr {
unsigned Alignment;
public:
AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
+ // FIXME: Should use addressable units, not bits, to match llvm
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Aligned;
@@ -187,11 +202,11 @@ class AnnotateAttr : public Attr {
std::string Annotation;
public:
AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {}
-
+
const std::string& getAnnotation() const { return Annotation; }
virtual Attr* clone(ASTContext &C) const { return ::new (C) AnnotateAttr(Annotation); }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Annotate;
@@ -203,11 +218,11 @@ class AsmLabelAttr : public Attr {
std::string Label;
public:
AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {}
-
+
const std::string& getLabel() const { return Label; }
-
+
virtual Attr* clone(ASTContext &C) const { return ::new (C) AsmLabelAttr(Label); }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == AsmLabel;
@@ -237,28 +252,28 @@ public:
ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
int getPriority() const { return priority; }
-
+
virtual Attr *clone(ASTContext &C) const { return ::new (C) ConstructorAttr(priority); }
// Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == Constructor; }
+ static bool classof(const Attr *A) { return A->getKind() == Constructor; }
static bool classof(const ConstructorAttr *A) { return true; }
-};
-
+};
+
class DestructorAttr : public Attr {
int priority;
public:
DestructorAttr(int p) : Attr(Destructor), priority(p) {}
int getPriority() const { return priority; }
-
+
virtual Attr *clone(ASTContext &C) const { return ::new (C) DestructorAttr(priority); }
// Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == Destructor; }
+ static bool classof(const Attr *A) { return A->getKind() == Destructor; }
static bool classof(const DestructorAttr *A) { return true; }
-};
-
+};
+
class GNUInlineAttr : public Attr {
public:
GNUInlineAttr() : Attr(GNUInline) {}
@@ -285,15 +300,16 @@ public:
static bool classof(const IBOutletAttr *A) { return true; }
};
+DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
-DEF_SIMPLE_ATTR(AnalyzerNoReturn);
+DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
class SectionAttr : public Attr {
std::string Name;
public:
SectionAttr(const std::string &N) : Attr(Section), Name(N) {}
-
+
const std::string& getName() const { return Name; }
virtual Attr *clone(ASTContext &C) const { return ::new (C) SectionAttr(Name); }
@@ -307,8 +323,8 @@ public:
DEF_SIMPLE_ATTR(Unavailable);
DEF_SIMPLE_ATTR(Unused);
-DEF_SIMPLE_ATTR(Used);
-DEF_SIMPLE_ATTR(Weak);
+DEF_SIMPLE_ATTR(Used);
+DEF_SIMPLE_ATTR(Weak);
DEF_SIMPLE_ATTR(WeakImport);
DEF_SIMPLE_ATTR(NoThrow);
DEF_SIMPLE_ATTR(Const);
@@ -320,14 +336,14 @@ class NonNullAttr : public Attr {
public:
NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
ArgNums(0), Size(0) {
-
+
if (size == 0) return;
assert(arg_nums);
ArgNums = new unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
}
-
+
virtual ~NonNullAttr() {
delete [] ArgNums;
}
@@ -339,7 +355,7 @@ public:
bool isNonNull(unsigned arg) const {
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
- }
+ }
virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); }
@@ -359,8 +375,8 @@ public:
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) FormatAttr(Type, formatIdx, firstArg);
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) FormatAttr(Type, formatIdx, firstArg);
}
// Implement isa/cast/dyncast/etc.
@@ -437,8 +453,8 @@ public:
virtual bool isMerged() const { return false; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) OverloadableAttr;
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) OverloadableAttr;
}
static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
@@ -465,15 +481,15 @@ public:
};
class FunctionDecl;
-
+
class CleanupAttr : public Attr {
FunctionDecl *FD;
-
+
public:
CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
const FunctionDecl *getFunctionDecl() const { return FD; }
-
+
virtual Attr *clone(ASTContext &C) const { return ::new (C) CleanupAttr(FD); }
// Implement isa/cast/dyncast/etc.
@@ -481,9 +497,9 @@ public:
static bool classof(const CleanupAttr *A) { return true; }
};
-DEF_SIMPLE_ATTR(Nodebug);
-DEF_SIMPLE_ATTR(WarnUnusedResult);
-DEF_SIMPLE_ATTR(Noinline);
+DEF_SIMPLE_ATTR(NoDebug);
+DEF_SIMPLE_ATTR(WarnUnusedResult);
+DEF_SIMPLE_ATTR(NoInline);
class RegparmAttr : public Attr {
unsigned NumParams;
@@ -493,11 +509,11 @@ public:
unsigned getNumParams() const { return NumParams; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) RegparmAttr(NumParams);
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) RegparmAttr(NumParams);
}
- // Implement isa/cast/dyncast/etc.
+ // Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Regparm; }
static bool classof(const RegparmAttr *A) { return true; }
};
@@ -512,23 +528,23 @@ public:
unsigned getYDim() const { return Y; }
unsigned getZDim() const { return Z; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
}
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == ReqdWorkGroupSize;
}
static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
-
+
// Checker-specific attributes.
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
#undef DEF_SIMPLE_ATTR
-
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
new file mode 100644
index 000000000000..a57bcc184a93
--- /dev/null
+++ b/include/clang/AST/CXXInheritance.h
@@ -0,0 +1,212 @@
+//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides routines that help analyzing C++ inheritance hierarchies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H
+#define LLVM_CLANG_AST_CXXINHERITANCE_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/ADT/SmallVector.h"
+#include <list>
+#include <map>
+#include <cassert>
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class NamedDecl;
+
+/// \brief Represents an element in a path from a derived class to a
+/// base class.
+///
+/// Each step in the path references the link from a
+/// derived class to one of its direct base classes, along with a
+/// base "number" that identifies which base subobject of the
+/// original derived class we are referencing.
+struct CXXBasePathElement {
+ /// \brief The base specifier that states the link from a derived
+ /// class to a base class, which will be followed by this base
+ /// path element.
+ const CXXBaseSpecifier *Base;
+
+ /// \brief The record decl of the class that the base is a base of.
+ const CXXRecordDecl *Class;
+
+ /// \brief Identifies which base class subobject (of type
+ /// \c Base->getType()) this base path element refers to.
+ ///
+ /// This value is only valid if \c !Base->isVirtual(), because there
+ /// is no base numbering for the zero or one virtual bases of a
+ /// given type.
+ int SubobjectNumber;
+};
+
+/// \brief Represents a path from a specific derived class
+/// (which is not represented as part of the path) to a particular
+/// (direct or indirect) base class subobject.
+///
+/// Individual elements in the path are described by the \c CXXBasePathElement
+/// structure, which captures both the link from a derived class to one of its
+/// direct bases and identification describing which base class
+/// subobject is being used.
+struct CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
+ /// \brief The set of declarations found inside this base class
+ /// subobject.
+ DeclContext::lookup_result Decls;
+};
+
+/// BasePaths - Represents the set of paths from a derived class to
+/// one of its (direct or indirect) bases. For example, given the
+/// following class hierachy:
+///
+/// @code
+/// class A { };
+/// class B : public A { };
+/// class C : public A { };
+/// class D : public B, public C{ };
+/// @endcode
+///
+/// There are two potential BasePaths to represent paths from D to a
+/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0)
+/// and another is (D,0)->(C,0)->(A,1). These two paths actually
+/// refer to two different base class subobjects of the same type,
+/// so the BasePaths object refers to an ambiguous path. On the
+/// other hand, consider the following class hierarchy:
+///
+/// @code
+/// class A { };
+/// class B : public virtual A { };
+/// class C : public virtual A { };
+/// class D : public B, public C{ };
+/// @endcode
+///
+/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0)
+/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them
+/// refer to the same base class subobject of type A (the virtual
+/// one), there is no ambiguity.
+class CXXBasePaths {
+ /// \brief The type from which this search originated.
+ CXXRecordDecl *Origin;
+
+ /// Paths - The actual set of paths that can be taken from the
+ /// derived class to the same base class.
+ std::list<CXXBasePath> Paths;
+
+ /// ClassSubobjects - Records the class subobjects for each class
+ /// type that we've seen. The first element in the pair says
+ /// whether we found a path to a virtual base for that class type,
+ /// while the element contains the number of non-virtual base
+ /// class subobjects for that class type. The key of the map is
+ /// the cv-unqualified canonical type of the base class subobject.
+ std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering>
+ ClassSubobjects;
+
+ /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
+ /// ambiguous paths while it is looking for a path from a derived
+ /// type to a base type.
+ bool FindAmbiguities;
+
+ /// RecordPaths - Whether Sema::IsDerivedFrom should record paths
+ /// while it is determining whether there are paths from a derived
+ /// type to a base type.
+ bool RecordPaths;
+
+ /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
+ /// if it finds a path that goes across a virtual base. The virtual class
+ /// is also recorded.
+ bool DetectVirtual;
+
+ /// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom
+ /// to help build the set of paths.
+ CXXBasePath ScratchPath;
+
+ /// DetectedVirtual - The base class that is virtual.
+ const RecordType *DetectedVirtual;
+
+ /// \brief Array of the declarations that have been found. This
+ /// array is constructed only if needed, e.g., to iterate over the
+ /// results within LookupResult.
+ NamedDecl **DeclsFound;
+ unsigned NumDeclsFound;
+
+ friend class CXXRecordDecl;
+
+ void ComputeDeclsFound();
+
+public:
+ typedef std::list<CXXBasePath>::const_iterator paths_iterator;
+ typedef NamedDecl **decl_iterator;
+
+ /// BasePaths - Construct a new BasePaths structure to record the
+ /// paths for a derived-to-base search.
+ explicit CXXBasePaths(bool FindAmbiguities = true,
+ bool RecordPaths = true,
+ bool DetectVirtual = true)
+ : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
+ NumDeclsFound(0) { }
+
+ ~CXXBasePaths() { delete [] DeclsFound; }
+
+ paths_iterator begin() const { return Paths.begin(); }
+ paths_iterator end() const { return Paths.end(); }
+
+ CXXBasePath& front() { return Paths.front(); }
+ const CXXBasePath& front() const { return Paths.front(); }
+
+ decl_iterator found_decls_begin();
+ decl_iterator found_decls_end();
+
+ /// \brief Determine whether the path from the most-derived type to the
+ /// given base type is ambiguous (i.e., it refers to multiple subobjects of
+ /// the same base type).
+ bool isAmbiguous(QualType BaseType);
+
+ /// \brief Whether we are finding multiple paths to detect ambiguities.
+ bool isFindingAmbiguities() const { return FindAmbiguities; }
+
+ /// \brief Whether we are recording paths.
+ bool isRecordingPaths() const { return RecordPaths; }
+
+ /// \brief Specify whether we should be recording paths or not.
+ void setRecordingPaths(bool RP) { RecordPaths = RP; }
+
+ /// \brief Whether we are detecting virtual bases.
+ bool isDetectingVirtual() const { return DetectVirtual; }
+
+ /// \brief The virtual base discovered on the path (if we are merely
+ /// detecting virtuals).
+ const RecordType* getDetectedVirtual() const {
+ return DetectedVirtual;
+ }
+
+ /// \brief Retrieve the type from which this base-paths search
+ /// began
+ CXXRecordDecl *getOrigin() const { return Origin; }
+ void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
+
+ /// \brief Clear the base-paths results.
+ void clear();
+
+ /// \brief Swap this data structure's contents with another CXXBasePaths
+ /// object.
+ void swap(CXXBasePaths &Other);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
new file mode 100644
index 000000000000..d7ac76dd32e4
--- /dev/null
+++ b/include/clang/AST/CanonicalType.h
@@ -0,0 +1,721 @@
+//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CanQual class template, which provides access to
+// canonical types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
+#define LLVM_CLANG_AST_CANONICAL_TYPE_H
+
+#include "clang/AST/Type.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/type_traits.h"
+#include <iterator>
+
+namespace clang {
+
+template<typename T> class CanProxy;
+template<typename T> struct CanProxyAdaptor;
+
+//----------------------------------------------------------------------------//
+// Canonical, qualified type template
+//----------------------------------------------------------------------------//
+
+/// \brief Represents a canonical, potentially-qualified type.
+///
+/// The CanQual template is a lightweight smart pointer that provides access
+/// to the canonical representation of a type, where all typedefs and other
+/// syntactic sugar has been eliminated. A CanQualType may also have various
+/// qualifiers (const, volatile, restrict) attached to it.
+///
+/// The template type parameter @p T is one of the Type classes (PointerType,
+/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
+/// type (or some subclass of that type). The typedef @c CanQualType is just
+/// a shorthand for @c CanQual<Type>.
+///
+/// An instance of @c CanQual<T> can be implicitly converted to a
+/// @c CanQual<U> when T is derived from U, which essentially provides an
+/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
+/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
+/// be implicitly converted to a QualType, but the reverse operation requires
+/// a call to ASTContext::getCanonicalType().
+///
+///
+template<typename T = Type>
+class CanQual {
+ /// \brief The actual, canonical type.
+ QualType Stored;
+
+public:
+ /// \brief Constructs a NULL canonical type.
+ CanQual() : Stored() { }
+
+ /// \brief Converting constructor that permits implicit upcasting of
+ /// canonical type pointers.
+ template<typename U>
+ CanQual(const CanQual<U>& Other,
+ typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
+
+ /// \brief Implicit conversion to the underlying pointer.
+ ///
+ /// Also provides the ability to use canonical types in a boolean context,
+ /// e.g.,
+ /// @code
+ /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
+ /// @endcode
+ operator const T*() const { return getTypePtr(); }
+
+ /// \brief Retrieve the underlying type pointer, which refers to a
+ /// canonical type.
+ T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
+
+ /// \brief Implicit conversion to a qualified type.
+ operator QualType() const { return Stored; }
+
+ /// \brief Retrieve a canonical type pointer with a different static type,
+ /// upcasting or downcasting as needed.
+ ///
+ /// The getAs() function is typically used to try to downcast to a
+ /// more specific (canonical) type in the type system. For example:
+ ///
+ /// @code
+ /// void f(CanQual<Type> T) {
+ /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
+ /// // look at Ptr's pointee type
+ /// }
+ /// }
+ /// @endcode
+ ///
+ /// \returns A proxy pointer to the same type, but with the specified
+ /// static type (@p U). If the dynamic type is not the specified static type
+ /// or a derived class thereof, a NULL canonical type.
+ template<typename U> CanProxy<U> getAs() const;
+
+ /// \brief Overloaded arrow operator that produces a canonical type
+ /// proxy.
+ CanProxy<T> operator->() const;
+
+ /// \brief Retrieve all qualifiers.
+ Qualifiers getQualifiers() const { return Stored.getQualifiers(); }
+
+ /// \brief Retrieve the const/volatile/restrict qualifiers.
+ unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
+
+ /// \brief Determines whether this type has any qualifiers
+ bool hasQualifiers() const { return Stored.hasQualifiers(); }
+
+ bool isConstQualified() const {
+ return Stored.isConstQualified();
+ }
+ bool isVolatileQualified() const {
+ return Stored.isVolatileQualified();
+ }
+ bool isRestrictQualified() const {
+ return Stored.isRestrictQualified();
+ }
+
+ /// \brief Retrieve the unqualified form of this type.
+ CanQual<T> getUnqualifiedType() const;
+
+ CanQual<T> getQualifiedType(unsigned TQs) const {
+ return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs));
+ }
+
+ /// \brief Determines whether this canonical type is more qualified than
+ /// the @p Other canonical type.
+ bool isMoreQualifiedThan(CanQual<T> Other) const {
+ return Stored.isMoreQualifiedThan(Other.Stored);
+ }
+
+ /// \brief Determines whether this canonical type is at least as qualified as
+ /// the @p Other canonical type.
+ bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
+ return Stored.isAtLeastAsQualifiedAs(Other.Stored);
+ }
+
+ /// \brief If the canonical type is a reference type, returns the type that
+ /// it refers to; otherwise, returns the type itself.
+ CanQual<Type> getNonReferenceType() const;
+
+ /// \brief Retrieve the internal representation of this canonical type.
+ void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
+
+ /// \brief Construct a canonical type from its internal representation.
+ static CanQual<T> getFromOpaquePtr(void *Ptr);
+
+ /// \brief Builds a canonical type from a QualType.
+ ///
+ /// This routine is inherently unsafe, because it requires the user to
+ /// ensure that the given type is a canonical type with the correct
+ // (dynamic) type.
+ static CanQual<T> CreateUnsafe(QualType Other);
+};
+
+template<typename T, typename U>
+inline bool operator==(CanQual<T> x, CanQual<U> y) {
+ return x.getAsOpaquePtr() == y.getAsOpaquePtr();
+}
+
+template<typename T, typename U>
+inline bool operator!=(CanQual<T> x, CanQual<U> y) {
+ return x.getAsOpaquePtr() != y.getAsOpaquePtr();
+}
+
+/// \brief Represents a canonical, potentially-qualified type.
+typedef CanQual<Type> CanQualType;
+
+//----------------------------------------------------------------------------//
+// Internal proxy classes used by canonical types
+//----------------------------------------------------------------------------//
+
+#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
+CanQualType Accessor() const { \
+return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
+}
+
+#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
+Type Accessor() const { return this->getTypePtr()->Accessor(); }
+
+/// \brief Base class of all canonical proxy types, which is responsible for
+/// storing the underlying canonical type and providing basic conversions.
+template<typename T>
+class CanProxyBase {
+protected:
+ CanQual<T> Stored;
+
+public:
+ /// \brief Retrieve the pointer to the underlying Type
+ T* getTypePtr() const { return Stored.getTypePtr(); }
+
+ /// \brief Implicit conversion to the underlying pointer.
+ ///
+ /// Also provides the ability to use canonical type proxies in a Boolean
+ // context,e.g.,
+ /// @code
+ /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
+ /// @endcode
+ operator const T*() const { return this->Stored.getTypePtr(); }
+
+ /// \brief Try to convert the given canonical type to a specific structural
+ /// type.
+ template<typename U> CanProxy<U> getAs() const {
+ return this->Stored.template getAs<U>();
+ }
+
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
+
+ // Type predicates
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
+
+ /// \brief Retrieve the proxy-adaptor type.
+ ///
+ /// This arrow operator is used when CanProxyAdaptor has been specialized
+ /// for the given type T. In that case, we reference members of the
+ /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
+ /// by the arrow operator in the primary CanProxyAdaptor template.
+ const CanProxyAdaptor<T> *operator->() const {
+ return static_cast<const CanProxyAdaptor<T> *>(this);
+ }
+};
+
+/// \brief Replacable canonical proxy adaptor class that provides the link
+/// between a canonical type and the accessors of the type.
+///
+/// The CanProxyAdaptor is a replaceable class template that is instantiated
+/// as part of each canonical proxy type. The primary template merely provides
+/// redirection to the underlying type (T), e.g., @c PointerType. One can
+/// provide specializations of this class template for each underlying type
+/// that provide accessors returning canonical types (@c CanQualType) rather
+/// than the more typical @c QualType, to propagate the notion of "canonical"
+/// through the system.
+template<typename T>
+struct CanProxyAdaptor : CanProxyBase<T> { };
+
+/// \brief Canonical proxy type returned when retrieving the members of a
+/// canonical type or as the result of the @c CanQual<T>::getAs member
+/// function.
+///
+/// The CanProxy type mainly exists as a proxy through which operator-> will
+/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
+/// type that provides canonical-type access to the fields of the type.
+template<typename T>
+class CanProxy : public CanProxyAdaptor<T> {
+public:
+ /// \brief Build a NULL proxy.
+ CanProxy() { }
+
+ /// \brief Build a proxy to the given canonical type.
+ CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
+
+ /// \brief Implicit conversion to the stored canonical type.
+ operator CanQual<T>() const { return this->Stored; }
+};
+
+} // end namespace clang
+
+namespace llvm {
+
+/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
+/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
+/// to return smart pointer (proxies?).
+template<typename T>
+struct simplify_type<const ::clang::CanQual<T> > {
+ typedef T* SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
+ return Val.getTypePtr();
+ }
+};
+template<typename T>
+struct simplify_type< ::clang::CanQual<T> >
+: public simplify_type<const ::clang::CanQual<T> > {};
+
+// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
+template<typename T>
+class PointerLikeTypeTraits<clang::CanQual<T> > {
+public:
+ static inline void *getAsVoidPointer(clang::CanQual<T> P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::CanQual<T> getFromVoidPointer(void *P) {
+ return clang::CanQual<T>::getFromOpaquePtr(P);
+ }
+ // qualifier information is encoded in the low bits.
+ enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm
+
+namespace clang {
+
+//----------------------------------------------------------------------------//
+// Canonical proxy adaptors for canonical type nodes.
+//----------------------------------------------------------------------------//
+
+/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
+/// into an iterator over CanQualTypes.
+template<typename InputIterator>
+class CanTypeIterator {
+ InputIterator Iter;
+
+public:
+ typedef CanQualType value_type;
+ typedef value_type reference;
+ typedef CanProxy<Type> pointer;
+ typedef typename std::iterator_traits<InputIterator>::difference_type
+ difference_type;
+ typedef typename std::iterator_traits<InputIterator>::iterator_category
+ iterator_category;
+
+ CanTypeIterator() : Iter() { }
+ explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
+
+ // Input iterator
+ reference operator*() const {
+ return CanQualType::CreateUnsafe(*Iter);
+ }
+
+ pointer operator->() const;
+
+ CanTypeIterator &operator++() {
+ ++Iter;
+ return *this;
+ }
+
+ CanTypeIterator operator++(int) {
+ CanTypeIterator Tmp(*this);
+ ++Iter;
+ return Tmp;
+ }
+
+ friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
+ return X.Iter == Y.Iter;
+ }
+ friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
+ return X.Iter != Y.Iter;
+ }
+
+ // Bidirectional iterator
+ CanTypeIterator &operator--() {
+ --Iter;
+ return *this;
+ }
+
+ CanTypeIterator operator--(int) {
+ CanTypeIterator Tmp(*this);
+ --Iter;
+ return Tmp;
+ }
+
+ // Random access iterator
+ reference operator[](difference_type n) const {
+ return CanQualType::CreateUnsafe(Iter[n]);
+ }
+
+ CanTypeIterator &operator+=(difference_type n) {
+ Iter += n;
+ return *this;
+ }
+
+ CanTypeIterator &operator-=(difference_type n) {
+ Iter -= n;
+ return *this;
+ }
+
+ friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
+ X += n;
+ return X;
+ }
+
+ friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
+ X += n;
+ return X;
+ }
+
+ friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
+ X -= n;
+ return X;
+ }
+
+ friend difference_type operator-(const CanTypeIterator &X,
+ const CanTypeIterator &Y) {
+ return X - Y;
+ }
+};
+
+template<>
+struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+};
+
+template<>
+struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<BlockPointerType>
+ : public CanProxyBase<BlockPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<LValueReferenceType>
+ : public CanProxyBase<LValueReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<RValueReferenceType>
+ : public CanProxyBase<RValueReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<MemberPointerType>
+ : public CanProxyBase<MemberPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
+};
+
+template<>
+struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+};
+
+template<>
+struct CanProxyAdaptor<ConstantArrayType>
+ : public CanProxyBase<ConstantArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
+};
+
+template<>
+struct CanProxyAdaptor<ConstantArrayWithExprType>
+ : public CanProxyBase<ConstantArrayWithExprType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
+};
+
+template<>
+struct CanProxyAdaptor<ConstantArrayWithoutExprType>
+ : public CanProxyBase<ConstantArrayWithoutExprType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
+};
+
+template<>
+struct CanProxyAdaptor<IncompleteArrayType>
+ : public CanProxyBase<IncompleteArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+};
+
+template<>
+struct CanProxyAdaptor<VariableArrayType>
+ : public CanProxyBase<VariableArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
+};
+
+template<>
+struct CanProxyAdaptor<DependentSizedArrayType>
+ : public CanProxyBase<DependentSizedArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
+};
+
+template<>
+struct CanProxyAdaptor<DependentSizedExtVectorType>
+ : public CanProxyBase<DependentSizedExtVectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
+};
+
+template<>
+struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
+};
+
+template<>
+struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionNoProtoType>
+ : public CanProxyBase<FunctionNoProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionProtoType>
+ : public CanProxyBase<FunctionProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs);
+ CanQualType getArgType(unsigned i) const {
+ return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
+ }
+
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
+
+ typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
+ arg_type_iterator;
+
+ arg_type_iterator arg_type_begin() const {
+ return arg_type_iterator(this->getTypePtr()->arg_type_begin());
+ }
+
+ arg_type_iterator arg_type_end() const {
+ return arg_type_iterator(this->getTypePtr()->arg_type_end());
+ }
+
+ // Note: canonical function types never have exception specifications
+};
+
+template<>
+struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+};
+
+template<>
+struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+};
+
+template<>
+struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+};
+
+template<>
+struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
+};
+
+template<>
+struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+};
+
+template<>
+struct CanProxyAdaptor<TemplateTypeParmType>
+ : public CanProxyBase<TemplateTypeParmType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName)
+};
+
+template<>
+struct CanProxyAdaptor<ObjCObjectPointerType>
+ : public CanProxyBase<ObjCObjectPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
+ getInterfaceType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
+
+ typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
+};
+
+//----------------------------------------------------------------------------//
+// Method and function definitions
+//----------------------------------------------------------------------------//
+template<typename T>
+inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
+ return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType());
+}
+
+template<typename T>
+inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
+ if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
+ return RefType->getPointeeType();
+ else
+ return *this;
+}
+
+template<typename T>
+CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
+ CanQual<T> Result;
+ Result.Stored.setFromOpaqueValue(Ptr);
+ assert((!Result || Result.Stored.isCanonical())
+ && "Type is not canonical!");
+ return Result;
+}
+
+template<typename T>
+CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
+ assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!");
+ assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
+ "Dynamic type does not meet the static type's requires");
+ CanQual<T> Result;
+ Result.Stored = Other;
+ return Result;
+}
+
+template<typename T>
+template<typename U>
+CanProxy<U> CanQual<T>::getAs() const {
+ if (Stored.isNull())
+ return CanProxy<U>();
+
+ if (isa<U>(Stored.getTypePtr()))
+ return CanQual<U>::CreateUnsafe(Stored);
+
+ return CanProxy<U>();
+}
+
+template<typename T>
+CanProxy<T> CanQual<T>::operator->() const {
+ return CanProxy<T>(*this);
+}
+
+template<typename InputIterator>
+typename CanTypeIterator<InputIterator>::pointer
+CanTypeIterator<InputIterator>::operator->() const {
+ return CanProxy<Type>(*this);
+}
+
+}
+
+
+#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 69a52869d818..7c326dee338c 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -16,6 +16,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/Redeclarable.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
@@ -26,23 +27,45 @@ class Stmt;
class CompoundStmt;
class StringLiteral;
class TemplateArgumentList;
+class MemberSpecializationInfo;
class FunctionTemplateSpecializationInfo;
-
+class TypeLoc;
+
+/// \brief A container of type source information.
+///
+/// A client can read the relevant info using TypeLoc wrappers, e.g:
+/// @code
+/// TypeLoc TL = DeclaratorInfo->getTypeLoc();
+/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL))
+/// PL->getStarLoc().print(OS, SrcMgr);
+/// @endcode
+///
+class DeclaratorInfo {
+ QualType Ty;
+ // Contains a memory block after the class, used for type source information,
+ // allocated by ASTContext.
+ friend class ASTContext;
+ DeclaratorInfo(QualType ty) : Ty(ty) { }
+public:
+ /// \brief Return the TypeLoc wrapper for the type source info.
+ TypeLoc getTypeLoc() const;
+};
+
/// TranslationUnitDecl - The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
ASTContext &Ctx;
-
+
explicit TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, 0, SourceLocation()),
DeclContext(TranslationUnit),
Ctx(ctx) {}
public:
ASTContext &getASTContext() const { return Ctx; }
-
+
static TranslationUnitDecl *Create(ASTContext &C);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
- static bool classof(const TranslationUnitDecl *D) { return true; }
+ static bool classof(const TranslationUnitDecl *D) { return true; }
static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
}
@@ -91,7 +114,7 @@ public:
/// manipulation, so it should be called only when performance doesn't matter.
/// For simple declarations, getNameAsCString() should suffice.
std::string getNameAsString() const { return Name.getAsString(); }
-
+
/// getQualifiedNameAsString - Returns human-readable qualified name for
/// declaration, like A::B::i, for i being member of namespace A::B.
/// If declaration is not member of context which can be named (record,
@@ -99,6 +122,25 @@ public:
/// Creating this name is expensive, so it should be called only when
/// performance doesn't matter.
std::string getQualifiedNameAsString() const;
+ std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const;
+
+ /// getNameForDiagnostic - Appends a human-readable name for this
+ /// declaration into the given string.
+ ///
+ /// This is the method invoked by Sema when displaying a NamedDecl
+ /// in a diagnostic. It does not necessarily produce the same
+ /// result as getNameAsString(); for example, class template
+ /// specializations are printed with their template arguments.
+ ///
+ /// TODO: use an API that doesn't require so many temporary strings
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const {
+ if (Qualified)
+ S += getQualifiedNameAsString(Policy);
+ else
+ S += getNameAsString();
+ }
/// declarationReplaces - Determine whether this declaration, if
/// known to be well-formed within its context, will replace the
@@ -118,7 +160,7 @@ public:
const NamedDecl *getUnderlyingDecl() const {
return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
}
-
+
static bool classof(const Decl *D) {
return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
}
@@ -128,7 +170,7 @@ public:
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext {
SourceLocation LBracLoc, RBracLoc;
-
+
// For extended namespace definitions:
//
// namespace A { int x; }
@@ -139,7 +181,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to itself.
NamespaceDecl *OrigNamespace, *NextNamespace;
-
+
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) {
OrigNamespace = this;
@@ -148,9 +190,20 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
-
+
virtual void Destroy(ASTContext& C);
+ // \brief Returns true if this is an anonymous namespace declaration.
+ //
+ // For example:
+ // namespace {
+ // ...
+ // };
+ // q.v. C++ [namespace.unnamed]
+ bool isAnonymousNamespace() const {
+ return !getIdentifier();
+ }
+
NamespaceDecl *getNextNamespace() { return NextNamespace; }
const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
@@ -159,7 +212,9 @@ public:
return OrigNamespace;
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
-
+
+ virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
+
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), RBracLoc);
}
@@ -168,7 +223,7 @@ public:
SourceLocation getRBracLoc() const { return RBracLoc; }
void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Namespace; }
static bool classof(const NamespaceDecl *D) { return true; }
@@ -180,20 +235,20 @@ public:
}
};
-/// ValueDecl - Represent the declaration of a variable (in which case it is
+/// ValueDecl - Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
-/// an enum constant.
+/// an enum constant.
class ValueDecl : public NamedDecl {
QualType DeclType;
protected:
ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
- DeclarationName N, QualType T)
+ DeclarationName N, QualType T)
: NamedDecl(DK, DC, L, N), DeclType(T) {}
public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= ValueFirst && D->getKind() <= ValueLast;
@@ -201,6 +256,29 @@ public:
static bool classof(const ValueDecl *D) { return true; }
};
+/// \brief Represents a ValueDecl that came out of a declarator.
+/// Contains type source information through DeclaratorInfo.
+class DeclaratorDecl : public ValueDecl {
+ DeclaratorInfo *DeclInfo;
+
+protected:
+ DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T, DeclaratorInfo *DInfo)
+ : ValueDecl(DK, DC, L, N, T), DeclInfo(DInfo) {}
+
+public:
+ DeclaratorInfo *getDeclaratorInfo() const { return DeclInfo; }
+ void setDeclaratorInfo(DeclaratorInfo *DInfo) { DeclInfo = DInfo; }
+
+ SourceLocation getTypeSpecStartLoc() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= DeclaratorFirst && D->getKind() <= DeclaratorLast;
+ }
+ static bool classof(const DeclaratorDecl *D) { return true; }
+};
+
/// \brief Structure used to store a statement, the constant value to
/// which it was evaluated (if any), and whether or not the statement
/// is an integral constant expression (if known).
@@ -222,9 +300,32 @@ struct EvaluatedStmt {
APValue Evaluated;
};
+// \brief Describes the kind of template specialization that a
+// particular template specialization declaration represents.
+enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation declaration request
+ /// (C++0x [temp.explicit]).
+ TSK_ExplicitInstantiationDeclaration,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation definition request
+ /// (C++ [temp.explicit]).
+ TSK_ExplicitInstantiationDefinition
+};
+
/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
-class VarDecl : public ValueDecl {
+class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
enum StorageClass {
None, Auto, Register, Extern, Static, PrivateExtern
@@ -236,81 +337,108 @@ public:
/// It is illegal to call this function with SC == None.
static const char *getStorageClassSpecifierString(StorageClass SC);
+protected:
+ /// \brief Placeholder type used in Init to denote an unparsed C++ default
+ /// argument.
+ struct UnparsedDefaultArgument;
+
+ /// \brief Placeholder type used in Init to denote an uninstantiated C++
+ /// default argument.
+ struct UninstantiatedDefaultArgument;
+
+ typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
+ UnparsedDefaultArgument *,
+ UninstantiatedDefaultArgument *> InitType;
+
+ /// \brief The initializer for this variable or, for a ParmVarDecl, the
+ /// C++ default argument.
+ mutable InitType Init;
+
private:
- mutable llvm::PointerUnion<Stmt *, EvaluatedStmt *> Init;
// FIXME: This can be packed into the bitfields in Decl.
unsigned SClass : 3;
bool ThreadSpecified : 1;
- bool HasCXXDirectInit : 1;
+ bool HasCXXDirectInit : 1;
/// DeclaredInCondition - Whether this variable was declared in a
/// condition, e.g., if (int x = foo()) { ... }.
bool DeclaredInCondition : 1;
- /// \brief The previous declaration of this variable.
- VarDecl *PreviousDeclaration;
-
- // Move to DeclGroup when it is implemented.
- SourceLocation TypeSpecStartLoc;
friend class StmtIteratorBase;
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
- QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation())
- : ValueDecl(DK, DC, L, Id, T), Init(),
+ QualType T, DeclaratorInfo *DInfo, StorageClass SC)
+ : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- DeclaredInCondition(false), PreviousDeclaration(0),
- TypeSpecStartLoc(TSSL) {
- SClass = SC;
+ DeclaredInCondition(false) {
+ SClass = SC;
}
+
+ typedef Redeclarable<VarDecl> redeclarable_base;
+ virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
- QualType T, StorageClass S,
- SourceLocation TypeSpecStartLoc = SourceLocation());
+ QualType T, DeclaratorInfo *DInfo, StorageClass S);
virtual ~VarDecl();
virtual void Destroy(ASTContext& C);
StorageClass getStorageClass() const { return (StorageClass)SClass; }
void setStorageClass(StorageClass SC) { SClass = SC; }
-
- virtual SourceRange getSourceRange() const;
- SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
- void setTypeSpecStartLoc(SourceLocation SL) {
- TypeSpecStartLoc = SL;
- }
+ virtual SourceRange getSourceRange() const;
- const Expr *getInit() const {
+ const Expr *getInit() const {
if (Init.isNull())
return 0;
const Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S)
- S = Init.get<EvaluatedStmt *>()->Value;
-
- return (const Expr*) S;
+ if (!S) {
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ S = ES->Value;
+ }
+ return (const Expr*) S;
}
- Expr *getInit() {
+ Expr *getInit() {
if (Init.isNull())
return 0;
Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S)
- S = Init.get<EvaluatedStmt *>()->Value;
+ if (!S) {
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ S = ES->Value;
+ }
- return (Expr*) S;
+ return (Expr*) S;
}
/// \brief Retrieve the address of the initializer expression.
Stmt **getInitAddress() {
- if (Init.is<Stmt *>())
- return reinterpret_cast<Stmt **>(&Init); // FIXME: ugly hack
- return &Init.get<EvaluatedStmt *>()->Value;
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ return &ES->Value;
+
+ // This union hack tip-toes around strict-aliasing rules.
+ union {
+ InitType *InitPtr;
+ Stmt **StmtPtr;
+ };
+
+ InitPtr = &Init;
+ return StmtPtr;
}
void setInit(ASTContext &C, Expr *I);
-
+
/// \brief Note that constant evaluation has computed the given
/// value for this variable's initializer.
void setEvaluatedValue(ASTContext &C, const APValue &Value) const {
@@ -325,7 +453,7 @@ public:
Eval->WasEvaluated = true;
Eval->Evaluated = Value;
}
-
+
/// \brief Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known.
APValue *getEvaluatedValue() const {
@@ -350,7 +478,7 @@ public:
///
/// \pre isInitKnownICE()
bool isInitICE() const {
- assert(isInitKnownICE() &&
+ assert(isInitKnownICE() &&
"Check whether we already know that the initializer is an ICE");
return Init.get<EvaluatedStmt *>()->IsICE;
}
@@ -392,7 +520,7 @@ public:
bool hasCXXDirectInitializer() const {
return HasCXXDirectInit;
}
-
+
/// isDeclaredInCondition - Whether this variable was declared as
/// part of a condition in an if/switch/while statement, e.g.,
/// @code
@@ -401,27 +529,21 @@ public:
bool isDeclaredInCondition() const {
return DeclaredInCondition;
}
- void setDeclaredInCondition(bool InCondition) {
- DeclaredInCondition = InCondition;
+ void setDeclaredInCondition(bool InCondition) {
+ DeclaredInCondition = InCondition;
}
- /// getPreviousDeclaration - Return the previous declaration of this
- /// variable.
- const VarDecl *getPreviousDeclaration() const { return PreviousDeclaration; }
-
- void setPreviousDeclaration(VarDecl *PrevDecl) {
- PreviousDeclaration = PrevDecl;
- }
+ virtual VarDecl *getCanonicalDecl();
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
if (getStorageClass() == None)
return !isFileVarDecl();
-
+
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
-
+
return getStorageClass() <= Register;
}
@@ -448,7 +570,7 @@ public:
return DC->getLookupContext()->isFunctionOrMethod();
return false;
}
-
+
/// \brief Determines whether this is a static data member.
///
/// This will only be true in C++, and applies to, e.g., the
@@ -462,6 +584,24 @@ public:
return getDeclContext()->isRecord();
}
+ /// \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();
+
+ /// \brief If this variable is a static data member, determine what kind of
+ /// template specialization or instantiation this is.
+ TemplateSpecializationKind getTemplateSpecializationKind();
+
+ /// \brief If this variable is an instantiation of a static data member of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo();
+
+ /// \brief For a static data member that was instantiated from a static
+ /// data member of a class template, set the template specialiation kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+
/// isFileVarDecl - Returns true for file scoped variable declaration.
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
@@ -471,16 +611,19 @@ public:
if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
return true;
}
+ if (isStaticDataMember())
+ return true;
+
return false;
}
/// \brief Determine whether this is a tentative definition of a
/// variable in C.
bool isTentativeDefinition(ASTContext &Context) const;
-
+
/// \brief Determines whether this variable is a variable with
/// external, C linkage.
- bool isExternC(ASTContext &Context) const;
+ bool isExternC() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
@@ -492,12 +635,12 @@ public:
class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, VarDecl::None) {}
+ IdentifierInfo *Id, QualType Tw)
+ : VarDecl(DK, DC, L, Id, Tw, /*DInfo=*/0, VarDecl::None) {}
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- QualType T);
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T);
// Implement isa/cast/dyncast/etc.
static bool classof(const ImplicitParamDecl *D) { return true; }
static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; }
@@ -509,44 +652,72 @@ class ParmVarDecl : public VarDecl {
/// FIXME: Also can be paced into the bitfields in Decl.
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
-
- /// Default argument, if any. [C++ Only]
- Expr *DefaultArg;
+
+ /// \brief Retrieves the fake "value" of an unparsed
+ static Expr *getUnparsedDefaultArgValue() {
+ uintptr_t Value = (uintptr_t)-1;
+ // Mask off the low bits
+ Value &= ~(uintptr_t)0x07;
+ return reinterpret_cast<Expr*> (Value);
+ }
+
protected:
ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T, StorageClass S,
- Expr *DefArg)
- : VarDecl(DK, DC, L, Id, T, S),
- objcDeclQualifier(OBJC_TQ_None), DefaultArg(DefArg) {}
+ IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
+ StorageClass S, Expr *DefArg)
+ : VarDecl(DK, DC, L, Id, T, DInfo, S), objcDeclQualifier(OBJC_TQ_None) {
+ setDefaultArg(DefArg);
+ }
public:
static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,IdentifierInfo *Id,
- QualType T, StorageClass S, Expr *DefArg);
-
+ QualType T, DeclaratorInfo *DInfo,
+ StorageClass S, Expr *DefArg);
+
ObjCDeclQualifier getObjCDeclQualifier() const {
return ObjCDeclQualifier(objcDeclQualifier);
}
void setObjCDeclQualifier(ObjCDeclQualifier QTVal) {
objcDeclQualifier = QTVal;
}
-
- const Expr *getDefaultArg() const {
+
+ const Expr *getDefaultArg() const {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
- return DefaultArg;
+ assert(!hasUninstantiatedDefaultArg() &&
+ "Default argument is not yet instantiated!");
+ return getInit();
}
- Expr *getDefaultArg() {
+ Expr *getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
- return DefaultArg;
+ assert(!hasUninstantiatedDefaultArg() &&
+ "Default argument is not yet instantiated!");
+ return getInit();
+ }
+ void setDefaultArg(Expr *defarg) {
+ Init = reinterpret_cast<Stmt *>(defarg);
+ }
+
+ /// \brief Retrieve the source range that covers the entire default
+ /// argument.
+ SourceRange getDefaultArgRange() const;
+ void setUninstantiatedDefaultArg(Expr *arg) {
+ Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
+ }
+ Expr *getUninstantiatedDefaultArg() {
+ return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ }
+ const Expr *getUninstantiatedDefaultArg() const {
+ return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
}
- void setDefaultArg(Expr *defarg) { DefaultArg = defarg; }
/// hasDefaultArg - Determines whether this parameter has a default argument,
/// either parsed or not.
bool hasDefaultArg() const {
- return DefaultArg != 0;
+ return getInit() || hasUnparsedDefaultArg() ||
+ hasUninstantiatedDefaultArg();
}
-
+
/// hasUnparsedDefaultArg - Determines whether this parameter has a
/// default argument that has not yet been parsed. This will occur
/// during the processing of a C++ class whose member functions have
@@ -558,7 +729,11 @@ public:
/// }; // x has a regular default argument now
/// @endcode
bool hasUnparsedDefaultArg() const {
- return DefaultArg == reinterpret_cast<Expr *>(-1);
+ return Init.is<UnparsedDefaultArgument*>();
+ }
+
+ bool hasUninstantiatedDefaultArg() const {
+ return Init.is<UninstantiatedDefaultArgument*>();
}
/// setUnparsedDefaultArg - Specify that this parameter has an
@@ -566,10 +741,12 @@ public:
/// real default argument via setDefaultArg when the class
/// definition enclosing the function declaration that owns this
/// default argument is completed.
- void setUnparsedDefaultArg() { DefaultArg = reinterpret_cast<Expr *>(-1); }
+ void setUnparsedDefaultArg() {
+ Init = (UnparsedDefaultArgument *)0;
+ }
QualType getOriginalType() const;
-
+
/// setOwningFunction - Sets the function declaration that owns this
/// ParmVarDecl. Since ParmVarDecls are often created before the
/// FunctionDecls that own them, this routine is required to update
@@ -577,9 +754,9 @@ public:
void setOwningFunction(DeclContext *FD) { setDeclContext(FD); }
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return (D->getKind() == ParmVar ||
- D->getKind() == OriginalParmVar);
+ D->getKind() == OriginalParmVar);
}
static bool classof(const ParmVarDecl *D) { return true; }
};
@@ -594,15 +771,17 @@ protected:
QualType OriginalType;
private:
OriginalParmVarDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ IdentifierInfo *Id, QualType T,
+ DeclaratorInfo *DInfo,
QualType OT, StorageClass S,
Expr *DefArg)
- : ParmVarDecl(OriginalParmVar, DC, L, Id, T, S, DefArg), OriginalType(OT) {}
+ : ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg),
+ OriginalType(OT) {}
public:
static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,IdentifierInfo *Id,
- QualType T, QualType OT,
- StorageClass S, Expr *DefArg);
+ QualType T, DeclaratorInfo *DInfo,
+ QualType OT, StorageClass S, Expr *DefArg);
void setOriginalType(QualType T) { OriginalType = T; }
@@ -610,9 +789,9 @@ public:
static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
static bool classof(const OriginalParmVarDecl *D) { return true; }
};
-
+
/// FunctionDecl - An instance of this class is created to represent a
-/// function declaration or definition.
+/// function declaration or definition.
///
/// Since a given function can be declared several times in a program,
/// there may be several FunctionDecls that correspond to that
@@ -621,46 +800,35 @@ public:
/// FunctionDecl (e.g., the translation unit); this FunctionDecl
/// contains all of the information known about the function. Other,
/// previous declarations of the function are available via the
-/// getPreviousDeclaration() chain.
-class FunctionDecl : public ValueDecl, public DeclContext {
+/// getPreviousDeclaration() chain.
+class FunctionDecl : public DeclaratorDecl, public DeclContext,
+ public Redeclarable<FunctionDecl> {
public:
enum StorageClass {
None, Extern, Static, PrivateExtern
};
-
-private:
+
+private:
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
ParmVarDecl **ParamInfo;
-
+
LazyDeclStmtPtr Body;
-
- /// PreviousDeclaration - A link to the previous declaration of this
- /// same function, NULL if this is the first declaration. For
- /// example, in the following code, the PreviousDeclaration can be
- /// traversed several times to see all three declarations of the
- /// function "f", the last of which is also a definition.
- ///
- /// int f(int x, int y = 1);
- /// int f(int x = 0, int y);
- /// int f(int x, int y) { return x + y; }
- FunctionDecl *PreviousDeclaration;
// FIXME: This can be packed into the bitfields in Decl.
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
unsigned SClass : 2;
bool IsInline : 1;
- bool C99InlineDefinition : 1;
bool IsVirtualAsWritten : 1;
bool IsPure : 1;
bool HasInheritedPrototype : 1;
bool HasWrittenPrototype : 1;
bool IsDeleted : 1;
+ bool IsTrivial : 1; // sunk from CXXMethodDecl
+ bool IsCopyAssignment : 1; // sunk from CXXMethodDecl
+ bool HasImplicitReturnZero : 1;
- // Move to DeclGroup when it is implemented.
- SourceLocation TypeSpecStartLoc;
-
/// \brief End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
@@ -672,42 +840,59 @@ private:
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
- ///
+ ///
/// For non-templates, this value will be NULL. For function
/// declarations that describe a function template, this will be a
/// pointer to a FunctionTemplateDecl. For member functions
- /// of class template specializations, this will be the
- /// FunctionDecl from which the member function was instantiated.
- /// For function template specializations, this will be a
+ /// of class template specializations, this will be a MemberSpecializationInfo
+ /// pointer containing information about the specialization.
+ /// For function template specializations, this will be a
/// FunctionTemplateSpecializationInfo, which contains information about
- /// the template being specialized and the template arguments involved in
+ /// the template being specialized and the template arguments involved in
/// that specialization.
- llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*,
- FunctionTemplateSpecializationInfo*>
+ llvm::PointerUnion3<FunctionTemplateDecl *,
+ MemberSpecializationInfo *,
+ FunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
- DeclarationName N, QualType T,
- StorageClass S, bool isInline,
- SourceLocation TSSL = SourceLocation())
- : ValueDecl(DK, DC, L, N, T),
+ DeclarationName N, QualType T, DeclaratorInfo *DInfo,
+ StorageClass S, bool isInline)
+ : DeclaratorDecl(DK, DC, L, N, T, DInfo),
DeclContext(DK),
- ParamInfo(0), Body(), PreviousDeclaration(0),
- SClass(S), IsInline(isInline), C99InlineDefinition(false),
- IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
- HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
+ ParamInfo(0), Body(),
+ SClass(S), IsInline(isInline),
+ IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
+ HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+ IsCopyAssignment(false),
+ HasImplicitReturnZero(false),
EndRangeLoc(L), TemplateOrSpecialization() {}
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
+ typedef Redeclarable<FunctionDecl> redeclarable_base;
+ virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName N, QualType T,
+ DeclarationName N, QualType T,
+ DeclaratorInfo *DInfo,
StorageClass S = None, bool isInline = false,
- bool hasWrittenPrototype = true,
- SourceLocation TSStartLoc = SourceLocation());
+ bool hasWrittenPrototype = true);
+
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), EndRangeLoc);
@@ -715,9 +900,6 @@ public:
void setLocEnd(SourceLocation E) {
EndRangeLoc = E;
}
-
- SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
- void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; }
/// getBody - Retrieve the body (definition) of the function. The
/// function body might be in any of the (re-)declarations of this
@@ -731,10 +913,6 @@ public:
return getBody(Definition);
}
- /// \brief If the function has a body that is immediately available,
- /// return it.
- Stmt *getBodyIfAvailable() const;
-
/// isThisDeclarationADefinition - Returns whether this specific
/// declaration of the function is also a definition. This does not
/// determine whether the function has been defined (e.g., in a
@@ -755,14 +933,30 @@ public:
bool isPure() const { return IsPure; }
void setPure(bool P = true) { IsPure = P; }
+ /// Whether this function is "trivial" in some specialized C++ senses.
+ /// Can only be true for default constructors, copy constructors,
+ /// copy assignment operators, and destructors. Not meaningful until
+ /// the class has been fully built by Sema.
+ bool isTrivial() const { return IsTrivial; }
+ void setTrivial(bool IT) { IsTrivial = IT; }
+
+ bool isCopyAssignment() const { return IsCopyAssignment; }
+ void setCopyAssignment(bool CA) { IsCopyAssignment = CA; }
+
+ /// Whether falling off this function implicitly returns null/zero.
+ /// If a more specific implicit return value is required, front-ends
+ /// should synthesize the appropriate return statements.
+ bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
+ void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }
+
/// \brief Whether this function has a prototype, either because one
/// was explicitly written or because it was "inherited" by merging
/// a declaration without a prototype with a declaration that has a
/// prototype.
- bool hasPrototype() const {
- return HasWrittenPrototype || HasInheritedPrototype;
+ bool hasPrototype() const {
+ return HasWrittenPrototype || HasInheritedPrototype;
}
-
+
bool hasWrittenPrototype() const { return HasWrittenPrototype; }
void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; }
@@ -798,39 +992,36 @@ public:
/// \brief Determines whether this function is a function with
/// external, C linkage.
- bool isExternC(ASTContext &Context) const;
+ bool isExternC() const;
/// \brief Determines whether this is a global function.
bool isGlobal() const;
- /// getPreviousDeclaration - Return the previous declaration of this
- /// function.
- const FunctionDecl *getPreviousDeclaration() const {
- return PreviousDeclaration;
- }
-
void setPreviousDeclaration(FunctionDecl * PrevDecl);
- unsigned getBuiltinID(ASTContext &Context) const;
+ virtual const FunctionDecl *getCanonicalDecl() const;
+ virtual FunctionDecl *getCanonicalDecl();
+
+ unsigned getBuiltinID() const;
unsigned getNumParmVarDeclsFromType() const;
-
+
// Iterator access to formal parameters.
unsigned param_size() const { return getNumParams(); }
typedef ParmVarDecl **param_iterator;
typedef ParmVarDecl * const *param_const_iterator;
-
+
param_iterator param_begin() { return ParamInfo; }
param_iterator param_end() { return ParamInfo+param_size(); }
-
+
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const { return ParamInfo+param_size(); }
-
+
/// getNumParams - Return the number of parameters this function must have
/// based on its functiontype. This is the length of the PararmInfo array
/// after it has been created.
unsigned getNumParams() const;
-
+
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
@@ -847,8 +1038,8 @@ public:
/// arguments (in C++).
unsigned getMinRequiredArguments() const;
- QualType getResultType() const {
- return getType()->getAsFunctionType()->getResultType();
+ QualType getResultType() const {
+ return getType()->getAs<FunctionType>()->getResultType();
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
void setStorageClass(StorageClass SC) { SClass = SC; }
@@ -856,27 +1047,11 @@ public:
bool isInline() const { return IsInline; }
void setInline(bool I) { IsInline = I; }
- /// \brief Whether this function is an "inline definition" as
- /// defined by C99.
- bool isC99InlineDefinition() const { return C99InlineDefinition; }
- void setC99InlineDefinition(bool I) { C99InlineDefinition = I; }
-
- /// \brief Determines whether this function has a gnu_inline
- /// attribute that affects its semantics.
- ///
- /// The gnu_inline attribute only introduces GNU inline semantics
- /// when all of the inline declarations of the function are marked
- /// gnu_inline.
- bool hasActiveGNUInlineAttribute(ASTContext &Context) const;
-
- /// \brief Determines whether this function is a GNU "extern
- /// inline", which is roughly the opposite of a C99 "extern inline"
- /// function.
- bool isExternGNUInline(ASTContext &Context) const;
-
+ bool isInlineDefinitionExternallyVisible() const;
+
/// isOverloadedOperator - Whether this function declaration
/// represents an C++ overloaded operator, e.g., "operator+".
- bool isOverloadedOperator() const {
+ bool isOverloadedOperator() const {
return getOverloadedOperator() != OO_None;
};
@@ -903,15 +1078,17 @@ public:
/// the FunctionDecl X<T>::A. When a complete definition of
/// X<int>::A is required, it will be instantiated from the
/// declaration returned by getInstantiatedFromMemberFunction().
- FunctionDecl *getInstantiatedFromMemberFunction() const {
- return TemplateOrSpecialization.dyn_cast<FunctionDecl*>();
- }
+ FunctionDecl *getInstantiatedFromMemberFunction() const;
+ /// \brief If this function is an instantiation of a member function of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
/// \brief Specify that this record is an instantiation of the
- /// member function RD.
- void setInstantiationOfMemberFunction(FunctionDecl *RD) {
- TemplateOrSpecialization = RD;
- }
+ /// member function FD.
+ void setInstantiationOfMemberFunction(FunctionDecl *FD,
+ TemplateSpecializationKind TSK);
/// \brief Retrieves the function template that is described by this
/// function declaration.
@@ -933,20 +1110,34 @@ public:
TemplateOrSpecialization = Template;
}
+ /// \brief Determine whether this function is a function template
+ /// specialization.
+ bool isFunctionTemplateSpecialization() const {
+ return getPrimaryTemplate() != 0;
+ }
+
+ /// \brief If this function is actually a function template specialization,
+ /// retrieve information about this function template specialization.
+ /// Otherwise, returns NULL.
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
+ return TemplateOrSpecialization.
+ dyn_cast<FunctionTemplateSpecializationInfo*>();
+ }
+
/// \brief Retrieve the primary template that this function template
/// specialization either specializes or was instantiated from.
///
/// If this function declaration is not a function template specialization,
/// returns NULL.
FunctionTemplateDecl *getPrimaryTemplate() const;
-
+
/// \brief Retrieve the template arguments used to produce this function
/// template specialization from the primary template.
///
/// If this function declaration is not a function template specialization,
/// returns NULL.
- const TemplateArgumentList *getTemplateSpecializationArgs() const;
-
+ const TemplateArgumentList *getTemplateSpecializationArgs() const;
+
/// \brief Specify that this function declaration is actually a function
/// template specialization.
///
@@ -957,19 +1148,30 @@ public:
///
/// \param TemplateArgs the template arguments that produced this
/// function template specialization from the template.
+ ///
+ /// \param InsertPos If non-NULL, the position in the function template
+ /// specialization set where the function template specialization data will
+ /// be inserted.
+ ///
+ /// \param TSK the kind of template specialization this is.
void setFunctionTemplateSpecialization(ASTContext &Context,
FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs,
- void *InsertPos);
+ void *InsertPos,
+ TemplateSpecializationKind TSK = TSK_ImplicitInstantiation);
- /// \brief Determine whether this is an explicit specialization of a
- /// function template or a member function of a class template.
- bool isExplicitSpecialization() const;
+ /// \brief Determine what kind of template instantiation this function
+ /// represents.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
- /// \brief Note that this is an explicit specialization of a function template
- /// or a member function of a class template.
- void setExplicitSpecialization(bool ES);
-
+ /// \brief Determine what kind of template instantiation this function
+ /// represents.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+
+ /// \brief Determine whether this is or was instantiated from an out-of-line
+ /// definition of a member function.
+ bool isOutOfLine() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
@@ -984,22 +1186,23 @@ public:
};
-/// FieldDecl - An instance of this class is created by Sema::ActOnField to
+/// FieldDecl - An instance of this class is created by Sema::ActOnField to
/// represent a member of a struct/union/class.
-class FieldDecl : public ValueDecl {
+class FieldDecl : public DeclaratorDecl {
// FIXME: This can be packed into the bitfields in Decl.
bool Mutable : 1;
Expr *BitWidth;
protected:
- FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T, Expr *BW, bool Mutable)
- : ValueDecl(DK, DC, L, Id, T), Mutable(Mutable), BitWidth(BW)
- { }
+ FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
+ Expr *BW, bool Mutable)
+ : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Mutable(Mutable), BitWidth(BW) {
+ }
public:
- static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T, Expr *BW,
- bool Mutable);
+ static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ DeclaratorInfo *DInfo, Expr *BW, bool Mutable);
/// isMutable - Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
@@ -1049,7 +1252,7 @@ public:
SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *E,
const llvm::APSInt &V);
-
+
virtual void Destroy(ASTContext& C);
const Expr *getInitExpr() const { return (const Expr*) Init; }
@@ -1058,11 +1261,11 @@ public:
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == EnumConstant; }
static bool classof(const EnumConstantDecl *D) { return true; }
-
+
friend class StmtIteratorBase;
};
@@ -1104,16 +1307,16 @@ class TypedefDecl : public TypeDecl {
/// UnderlyingType - This is the type the typedef is set to.
QualType UnderlyingType;
TypedefDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T)
+ IdentifierInfo *Id, QualType T)
: TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {}
virtual ~TypedefDecl() {}
public:
-
+
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,IdentifierInfo *Id,
QualType T);
-
+
QualType getUnderlyingType() const { return UnderlyingType; }
void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
@@ -1123,16 +1326,17 @@ public:
};
class TypedefDecl;
-
+
/// TagDecl - Represents the declaration of a struct/union/class/enum.
-class TagDecl : public TypeDecl, public DeclContext {
+class TagDecl
+ : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
public:
- enum TagKind {
- TK_struct,
- TK_union,
- TK_class,
- TK_enum
- };
+ // This is really ugly.
+ typedef ElaboratedType::TagKind TagKind;
+ static const TagKind TK_struct = ElaboratedType::TK_struct;
+ static const TagKind TK_union = ElaboratedType::TK_union;
+ static const TagKind TK_class = ElaboratedType::TK_class;
+ static const TagKind TK_enum = ElaboratedType::TK_enum;
private:
// FIXME: This can be packed into the bitfields in Decl.
@@ -1142,21 +1346,48 @@ private:
/// IsDefinition - True if this is a definition ("struct foo {};"), false if
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
-
+
/// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef,
/// this points to the TypedefDecl. Used for mangling.
TypedefDecl *TypedefForAnonDecl;
-
+
+ SourceLocation TagKeywordLoc;
+ SourceLocation RBraceLoc;
+
protected:
TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id)
- : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0) {
+ IdentifierInfo *Id, TagDecl *PrevDecl,
+ SourceLocation TKL = SourceLocation())
+ : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0),
+ TagKeywordLoc(TKL) {
assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");
TagDeclKind = TK;
IsDefinition = false;
+ setPreviousDeclaration(PrevDecl);
}
+
+ typedef Redeclarable<TagDecl> redeclarable_base;
+ virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
public:
-
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+
+ SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; }
+ void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; }
+
+ virtual SourceRange getSourceRange() const;
+
+ virtual TagDecl* getCanonicalDecl();
+
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
return IsDefinition;
@@ -1168,7 +1399,7 @@ public:
bool isDependentType() const { return isDependentContext(); }
/// @brief Starts the definition of this tag declaration.
- ///
+ ///
/// This method should be invoked at the beginning of the definition
/// of this tag declaration. It will set the tag type into a state
/// where it is in the process of being defined.
@@ -1177,7 +1408,7 @@ public:
/// @brief Completes the definition of this tag declaration.
void completeDefinition();
- /// getDefinition - Returns the TagDecl that actually defines this
+ /// getDefinition - Returns the TagDecl that actually defines this
/// struct/union/class/enum. When determining whether or not a
/// struct/union/class/enum is completely defined, one should use this method
/// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a
@@ -1185,17 +1416,16 @@ public:
/// struct/union/class/enum type is defined. This method returns NULL if
/// there is no TagDecl that defines the struct/union/class/enum.
TagDecl* getDefinition(ASTContext& C) const;
-
+
const char *getKindName() const {
- switch (getTagKind()) {
- default: assert(0 && "Unknown TagKind!");
- case TK_struct: return "struct";
- case TK_union: return "union";
- case TK_class: return "class";
- case TK_enum: return "enum";
- }
+ return ElaboratedType::getNameForTagKind(getTagKind());
}
+ /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
+ /// into a tag kind. It is an error to provide a type specifier
+ /// which *isn't* a tag kind here.
+ static TagKind getTagKindForTypeSpec(unsigned TypeSpec);
+
TagKind getTagKind() const {
return TagKind(TagDeclKind);
}
@@ -1206,10 +1436,10 @@ public:
bool isClass() const { return getTagKind() == TK_class; }
bool isUnion() const { return getTagKind() == TK_union; }
bool isEnum() const { return getTagKind() == TK_enum; }
-
+
TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; }
void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; }
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TagFirst && D->getKind() <= TagLast;
@@ -1240,15 +1470,19 @@ class EnumDecl : public TagDecl {
EnumDecl *InstantiatedFrom;
EnumDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id)
- : TagDecl(Enum, TK_enum, DC, L, Id), InstantiatedFrom(0) {
+ IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
+ : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
IntegerType = QualType();
}
public:
+ EnumDecl *getCanonicalDecl() {
+ return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ }
+
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
- EnumDecl *PrevDecl);
-
+ SourceLocation TKL, EnumDecl *PrevDecl);
+
virtual void Destroy(ASTContext& C);
/// completeDefinition - When created, the EnumDecl corresponds to a
@@ -1257,16 +1491,16 @@ public:
/// added (via DeclContext::addDecl). NewType is the new underlying
/// type of the enumeration type.
void completeDefinition(ASTContext &C, QualType NewType);
-
+
// enumerator_iterator - Iterates through the enumerators of this
// enumeration.
typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
- enumerator_iterator enumerator_begin() const {
+ enumerator_iterator enumerator_begin() const {
return enumerator_iterator(this->decls_begin());
}
- enumerator_iterator enumerator_end() const {
+ enumerator_iterator enumerator_end() const {
return enumerator_iterator(this->decls_end());
}
@@ -1307,18 +1541,24 @@ class RecordDecl : public TagDecl {
/// anonymous struct or union.
bool AnonymousStructOrUnion : 1;
+ /// HasObjectMember - This is true if this struct has at least one
+ /// member containing an object
+ bool HasObjectMember : 1;
+
protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id);
+ SourceLocation L, IdentifierInfo *Id,
+ RecordDecl *PrevDecl, SourceLocation TKL);
virtual ~RecordDecl();
public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL = SourceLocation(),
RecordDecl* PrevDecl = 0);
virtual void Destroy(ASTContext& C);
-
+
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
@@ -1328,7 +1568,7 @@ public:
/// type declared, e.g.,
/// @code
/// union { int i; float f; };
- /// @endcode
+ /// @endcode
/// is an anonymous union but neither of the following are:
/// @code
/// union X { int i; float f; };
@@ -1339,6 +1579,9 @@ public:
AnonymousStructOrUnion = Anon;
}
+ bool hasObjectMember() const { return HasObjectMember; }
+ void setHasObjectMember (bool val) { HasObjectMember = val; }
+
/// \brief Determines whether this declaration represents the
/// injected class name.
///
@@ -1354,7 +1597,7 @@ public:
/// \endcode
bool isInjectedClassName() const;
- /// getDefinition - Returns the RecordDecl that actually defines this
+ /// getDefinition - Returns the RecordDecl that actually defines this
/// struct/union/class. When determining whether or not a struct/union/class
/// is completely defined, one should use this method as opposed to
/// 'isDefinition'. 'isDefinition' indicates whether or not a specific
@@ -1364,7 +1607,7 @@ public:
RecordDecl* getDefinition(ASTContext& C) const {
return cast_or_null<RecordDecl>(TagDecl::getDefinition(C));
}
-
+
// Iterator access to field members. The field iterator only visits
// the non-static data members of this class, ignoring any static
// data members, functions, constructors, destructors, etc.
@@ -1379,7 +1622,7 @@ public:
// field_empty - Whether there are any fields (non-static data
// members) in this record.
- bool field_empty() const {
+ bool field_empty() const {
return field_begin() == field_end();
}
@@ -1408,7 +1651,7 @@ public:
static bool classof(const Decl *D) {
return D->getKind() == FileScopeAsm;
}
- static bool classof(const FileScopeAsmDecl *D) { return true; }
+ static bool classof(const FileScopeAsmDecl *D) { return true; }
};
/// BlockDecl - This represents a block literal declaration, which is like an
@@ -1423,12 +1666,12 @@ class BlockDecl : public Decl, public DeclContext {
/// no formals.
ParmVarDecl **ParamInfo;
unsigned NumParams;
-
+
Stmt *Body;
-
+
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
- : Decl(Block, DC, CaretLoc), DeclContext(Block),
+ : Decl(Block, DC, CaretLoc), DeclContext(Block),
isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {}
virtual ~BlockDecl();
@@ -1441,7 +1684,7 @@ public:
bool IsVariadic() const { return isVariadic; }
void setIsVariadic(bool value) { isVariadic = value; }
-
+
CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; }
Stmt *getBody() const { return (Stmt*) Body; }
void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
@@ -1450,14 +1693,14 @@ public:
unsigned param_size() const { return getNumParams(); }
typedef ParmVarDecl **param_iterator;
typedef ParmVarDecl * const *param_const_iterator;
-
+
bool param_empty() const { return NumParams == 0; }
param_iterator param_begin() { return ParamInfo; }
param_iterator param_end() { return ParamInfo+param_size(); }
-
+
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const { return ParamInfo+param_size(); }
-
+
unsigned getNumParams() const;
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
@@ -1468,10 +1711,10 @@ public:
return ParamInfo[i];
}
void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams);
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Block; }
- static bool classof(const BlockDecl *D) { return true; }
+ static bool classof(const BlockDecl *D) { return true; }
static DeclContext *castToDeclContext(const BlockDecl *D) {
return static_cast<DeclContext *>(const_cast<BlockDecl*>(D));
}
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 0bce2f84c7ba..9e88871565f1 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -37,6 +37,7 @@ class ObjCCategoryDecl;
class ObjCProtocolDecl;
class ObjCImplementationDecl;
class ObjCCategoryImplDecl;
+class ObjCImplDecl;
class LinkageSpecDecl;
class BlockDecl;
class DeclarationName;
@@ -59,8 +60,8 @@ public:
namespace clang {
-/// Decl - This represents one declaration (or definition), e.g. a variable,
-/// typedef, function, struct, etc.
+/// Decl - This represents one declaration (or definition), e.g. a variable,
+/// typedef, function, struct, etc.
///
class Decl {
public:
@@ -68,7 +69,7 @@ public:
enum Kind {
#define DECL(Derived, Base) Derived,
#define DECL_RANGE(CommonBase, Start, End) \
- CommonBase##First = Start, CommonBase##Last = End,
+ CommonBase##First = Start, CommonBase##Last = End,
#define LAST_DECL_RANGE(CommonBase, Start, End) \
CommonBase##First = Start, CommonBase##Last = End
#include "clang/AST/DeclNodes.def"
@@ -78,7 +79,9 @@ public:
/// namespaces, labels, tags, members and ordinary
/// identifiers. These are meant as bitmasks, so that searches in
/// C++ can look into the "tag" namespace during ordinary lookup. We
- /// use additional namespaces for Objective-C entities.
+ /// use additional namespaces for Objective-C entities. We also
+ /// put C++ friend declarations (of previously-undeclared entities) in
+ /// shadow namespaces.
enum IdentifierNamespace {
IDNS_Label = 0x1,
IDNS_Tag = 0x2,
@@ -86,9 +89,11 @@ public:
IDNS_Ordinary = 0x8,
IDNS_ObjCProtocol = 0x10,
IDNS_ObjCImplementation = 0x20,
- IDNS_ObjCCategoryImpl = 0x40
+ IDNS_ObjCCategoryImpl = 0x40,
+ IDNS_OrdinaryFriend = 0x80,
+ IDNS_TagFriend = 0x100
};
-
+
/// ObjCDeclQualifier - Qualifier used on types in method declarations
/// for remote messaging. They are meant for the arguments though and
/// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
@@ -101,7 +106,7 @@ public:
OBJC_TQ_Byref = 0x10,
OBJC_TQ_Oneway = 0x20
};
-
+
private:
/// NextDeclInContext - The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
@@ -114,8 +119,8 @@ private:
DeclContext *SemanticDC;
DeclContext *LexicalDC;
};
-
-
+
+
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
/// For declarations that don't contain C++ scope specifiers, it contains
/// the DeclContext where the Decl was declared.
@@ -139,16 +144,16 @@ private:
inline DeclContext *getSemanticDC() const {
return DeclCtx.get<DeclContext*>();
}
-
+
/// Loc - The location that this decl.
SourceLocation Loc;
-
+
/// DeclKind - This indicates which class this is.
Kind DeclKind : 8;
-
+
/// InvalidDecl - This indicates a semantic error occurred.
unsigned int InvalidDecl : 1;
-
+
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned int HasAttrs : 1;
@@ -162,23 +167,23 @@ private:
protected:
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
- unsigned IdentifierNamespace : 8;
-
+ unsigned IdentifierNamespace : 16;
+
private:
#ifndef NDEBUG
void CheckAccessDeclContext() const;
#else
void CheckAccessDeclContext() const { }
#endif
-
+
protected:
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
- Decl(Kind DK, DeclContext *DC, SourceLocation L)
- : NextDeclInContext(0), DeclCtx(DC),
+ Decl(Kind DK, DeclContext *DC, SourceLocation L)
+ : NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
@@ -201,7 +206,7 @@ public:
Kind getKind() const { return DeclKind; }
const char *getDeclKindName() const;
-
+
Decl *getNextDeclInContext() { return NextDeclInContext; }
const Decl *getNextDeclInContext() const { return NextDeclInContext; }
@@ -219,16 +224,18 @@ public:
return const_cast<Decl*>(this)->getTranslationUnitDecl();
}
+ bool isInAnonymousNamespace() const;
+
ASTContext &getASTContext() const;
-
+
void setAccess(AccessSpecifier AS) {
- Access = AS;
+ Access = AS;
CheckAccessDeclContext();
}
-
- AccessSpecifier getAccess() const {
+
+ AccessSpecifier getAccess() const {
CheckAccessDeclContext();
- return AccessSpecifier(Access);
+ return AccessSpecifier(Access);
}
bool hasAttrs() const { return HasAttrs; }
@@ -246,11 +253,11 @@ public:
return V;
return 0;
}
-
+
template<typename T> bool hasAttr() const {
return getAttr<T>() != 0;
}
-
+
/// setInvalidDecl - Indicates the Decl had a semantic error. This
/// allows for graceful error recovery.
void setInvalidDecl(bool Invalid = true) { InvalidDecl = Invalid; }
@@ -261,12 +268,12 @@ public:
/// was written explicitly in the source code.
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
-
+
/// \brief Whether this declaration was used, meaning that a definition
/// is required.
bool isUsed() const { return Used; }
void setUsed(bool U = true) { Used = U; }
-
+
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@@ -275,7 +282,7 @@ public:
}
static unsigned getIdentifierNamespaceForKind(Kind DK);
-
+
/// getLexicalDeclContext - The declaration context where this Decl was
/// lexically declared (LexicalDC). May be different from
/// getDeclContext() (SemanticDC).
@@ -298,7 +305,7 @@ public:
bool isOutOfLine() const {
return getLexicalDeclContext() != getDeclContext();
}
-
+
/// setDeclContext - Set both the semantic and lexical DeclContext
/// to DC.
void setDeclContext(DeclContext *DC);
@@ -311,6 +318,72 @@ public:
// be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
+ /// \brief Retrieves the "canonical" declaration of the given declaration.
+ virtual Decl *getCanonicalDecl() { return this; }
+ const Decl *getCanonicalDecl() const {
+ return const_cast<Decl*>(this)->getCanonicalDecl();
+ }
+
+ /// \brief Whether this particular Decl is a canonical one.
+ bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
+
+protected:
+ /// \brief Returns the next redeclaration or itself if this is the only decl.
+ ///
+ /// Decl subclasses that can be redeclared should override this method so that
+ /// Decl::redecl_iterator can iterate over them.
+ virtual Decl *getNextRedeclaration() { return this; }
+
+public:
+ /// \brief Iterates through all the redeclarations of the same decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ Decl *Current;
+ Decl *Starter;
+
+ public:
+ typedef Decl* value_type;
+ typedef Decl* reference;
+ typedef Decl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ Decl *Next = Current->getNextRedeclaration();
+ assert(Next && "Should return next redeclaration or itself, never null!");
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same decl.
+ /// It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<Decl*>(this));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
/// getBody - If this Decl represents a declaration for a body of code,
/// such as a function or method definition, this method returns the
/// top-level Stmt* of that body. Otherwise this method returns null.
@@ -327,33 +400,71 @@ public:
static void addDeclKind(Kind k);
static bool CollectingStats(bool Enable = false);
static void PrintStats();
-
+
/// isTemplateParameter - Determines whether this declaration is a
/// template parameter.
bool isTemplateParameter() const;
-
+
/// isTemplateParameter - Determines whether this declaration is a
/// template parameter pack.
bool isTemplateParameterPack() const;
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;
-
+
+ /// \brief Changes the namespace of this declaration to reflect that it's
+ /// the object of a friend declaration.
+ ///
+ /// These declarations appear in the lexical context of the friending
+ /// class, but in the semantic context of the actual entity. This property
+ /// applies only to a specific decl object; other redeclarations of the
+ /// same entity may not (and probably don't) share this property.
+ void setObjectOfFriendDecl(bool PreviouslyDeclared) {
+ unsigned OldNS = IdentifierNamespace;
+ assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary ||
+ OldNS == (IDNS_Tag | IDNS_Ordinary))
+ && "unsupported namespace for undeclared friend");
+ if (!PreviouslyDeclared) IdentifierNamespace = 0;
+
+ if (OldNS == IDNS_Tag)
+ IdentifierNamespace |= IDNS_TagFriend;
+ else
+ IdentifierNamespace |= IDNS_OrdinaryFriend;
+ }
+
+ enum FriendObjectKind {
+ FOK_None, // not a friend object
+ FOK_Declared, // a friend of a previously-declared entity
+ FOK_Undeclared // a friend of a previously-undeclared entity
+ };
+
+ /// \brief Determines whether this declaration is the object of a
+ /// friend declaration and, if so, what kind.
+ ///
+ /// There is currently no direct way to find the associated FriendDecl.
+ FriendObjectKind getFriendObjectKind() const {
+ unsigned mask
+ = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
+ if (!mask) return FOK_None;
+ return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ?
+ FOK_Declared : FOK_Undeclared);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
-
+
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
- void print(llvm::raw_ostream &Out, unsigned Indentation = 0);
+ void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
- unsigned Indentation = 0);
+ unsigned Indentation = 0) const;
static void printGroup(Decl** Begin, unsigned NumDecls,
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
- void dump();
+ void dump() const;
private:
const Attr *getAttrsImpl() const;
@@ -371,10 +482,10 @@ public:
PrettyStackTraceDecl(Decl *theDecl, SourceLocation L,
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
-
+
virtual void print(llvm::raw_ostream &OS) const;
-};
-
+};
+
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
@@ -386,8 +497,6 @@ public:
/// TagDecl
/// ObjCMethodDecl
/// ObjCContainerDecl
-/// ObjCCategoryImplDecl
-/// ObjCImplementationDecl
/// LinkageSpecDecl
/// BlockDecl
///
@@ -421,9 +530,9 @@ class DeclContext {
mutable Decl *LastDecl;
protected:
- DeclContext(Decl::Kind K)
+ DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
- ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
+ ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { }
void DestroyDecls(ASTContext &C);
@@ -443,7 +552,7 @@ public:
const DeclContext *getParent() const {
return const_cast<DeclContext*>(this)->getParent();
}
-
+
/// getLexicalParent - Returns the containing lexical DeclContext. May be
/// different from getParent, e.g.:
///
@@ -458,8 +567,14 @@ public:
}
const DeclContext *getLexicalParent() const {
return const_cast<DeclContext*>(this)->getLexicalParent();
- }
+ }
+ DeclContext *getLookupParent();
+
+ const DeclContext *getLookupParent() const {
+ return const_cast<DeclContext*>(this)->getLookupParent();
+ }
+
ASTContext &getParentASTContext() const {
return cast<Decl>(this)->getASTContext();
}
@@ -499,10 +614,10 @@ public:
/// context are semantically declared in the nearest enclosing
/// non-transparent (opaque) context but are lexically declared in
/// this context. For example, consider the enumerators of an
- /// enumeration type:
+ /// enumeration type:
/// @code
/// enum E {
- /// Val1
+ /// Val1
/// };
/// @endcode
/// Here, E is a transparent context, so its enumerator (Val1) will
@@ -512,13 +627,16 @@ public:
/// inline namespaces.
bool isTransparentContext() const;
- bool Encloses(DeclContext *DC) const {
- for (; DC; DC = DC->getParent())
- if (DC == this)
- return true;
- return false;
+ /// \brief Determine whether this declaration context is equivalent
+ /// to the declaration context DC.
+ bool Equals(DeclContext *DC) {
+ return this->getPrimaryContext() == DC->getPrimaryContext();
}
+ /// \brief Determine whether this declaration context encloses the
+ /// declaration context DC.
+ bool Encloses(DeclContext *DC);
+
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
/// of classes, multiple definitions of namespaces, etc.), each with
@@ -535,7 +653,7 @@ public:
const DeclContext *getLookupContext() const {
return const_cast<DeclContext *>(this)->getLookupContext();
}
-
+
/// \brief Retrieve the nearest enclosing namespace context.
DeclContext *getEnclosingNamespaceContext();
const DeclContext *getEnclosingNamespaceContext() const {
@@ -591,16 +709,16 @@ public:
return tmp;
}
- friend bool operator==(decl_iterator x, decl_iterator y) {
+ friend bool operator==(decl_iterator x, decl_iterator y) {
return x.Current == y.Current;
}
- friend bool operator!=(decl_iterator x, decl_iterator y) {
+ friend bool operator!=(decl_iterator x, decl_iterator y) {
return x.Current != y.Current;
}
};
/// decls_begin/decls_end - Iterate over the declarations stored in
- /// this context.
+ /// this context.
decl_iterator decls_begin() const;
decl_iterator decls_end() const;
bool decls_empty() const;
@@ -616,7 +734,7 @@ public:
/// will either be NULL or will point to a declaration of
/// type SpecificDecl.
DeclContext::decl_iterator Current;
-
+
/// SkipToNextDecl - Advances the current position up to the next
/// declaration of type SpecificDecl that also meets the criteria
/// required by Acceptable.
@@ -661,13 +779,13 @@ public:
++(*this);
return tmp;
}
-
+
friend bool
operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current == y.Current;
}
-
- friend bool
+
+ friend bool
operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current != y.Current;
}
@@ -688,7 +806,7 @@ public:
/// will either be NULL or will point to a declaration of
/// type SpecificDecl.
DeclContext::decl_iterator Current;
-
+
/// SkipToNextDecl - Advances the current position up to the next
/// declaration of type SpecificDecl that also meets the criteria
/// required by Acceptable.
@@ -735,13 +853,13 @@ public:
++(*this);
return tmp;
}
-
+
friend bool
operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
return x.Current == y.Current;
}
-
- friend bool
+
+ friend bool
operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
return x.Current != y.Current;
}
@@ -761,6 +879,14 @@ public:
/// semantic context via makeDeclVisibleInContext.
void addDecl(Decl *D);
+ /// @brief Add the declaration D to this context without modifying
+ /// any lookup tables.
+ ///
+ /// This is useful for some operations in dependent contexts where
+ /// the semantic context might not be dependent; this basically
+ /// only happens with friends.
+ void addHiddenDecl(Decl *D);
+
/// lookup_iterator - An iterator that provides access to the results
/// of looking up a name within this context.
typedef NamedDecl **lookup_iterator;
@@ -795,12 +921,16 @@ public:
/// visible from this context, as determined by
/// NamedDecl::declarationReplaces, the previous declaration will be
/// replaced with D.
- void makeDeclVisibleInContext(NamedDecl *D);
+ ///
+ /// @param Recoverable true if it's okay to not add this decl to
+ /// the lookup tables because it can be easily recovered by walking
+ /// the declaration chains.
+ void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
-
+
typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
udir_iterator_range getUsingDirectives() const;
@@ -824,8 +954,8 @@ public:
/// \brief State whether this DeclContext has external storage for
/// declarations lexically in this context.
- void setHasExternalLexicalStorage(bool ES = true) {
- ExternalLexicalStorage = ES;
+ void setHasExternalLexicalStorage(bool ES = true) {
+ ExternalLexicalStorage = ES;
}
/// \brief Whether this DeclContext has external storage containing
@@ -834,8 +964,8 @@ public:
/// \brief State whether this DeclContext has external storage for
/// declarations visible in this context.
- void setHasExternalVisibleStorage(bool ES = true) {
- ExternalVisibleStorage = ES;
+ void setHasExternalVisibleStorage(bool ES = true) {
+ ExternalVisibleStorage = ES;
}
static bool classof(const Decl *D);
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index c523e96e03b0..c858c5c0df78 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -14,46 +14,51 @@
#ifndef LLVM_CLANG_AST_DECLCXX_H
#define LLVM_CLANG_AST_DECLCXX_H
+#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
class ClassTemplateDecl;
-class CXXRecordDecl;
+class ClassTemplateSpecializationDecl;
+class CXXBasePath;
+class CXXBasePaths;
class CXXConstructorDecl;
-class CXXDestructorDecl;
class CXXConversionDecl;
+class CXXDestructorDecl;
class CXXMethodDecl;
-class ClassTemplateSpecializationDecl;
-
-/// \brief Represents any kind of function declaration, whether it is a
+class CXXRecordDecl;
+class CXXMemberLookupCriteria;
+
+/// \brief Represents any kind of function declaration, whether it is a
/// concrete function or a function template.
class AnyFunctionDecl {
NamedDecl *Function;
-
+
AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
-
+
public:
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
AnyFunctionDecl(FunctionTemplateDecl *FTD);
-
- /// \brief Implicily converts any function or function template into a
+
+ /// \brief Implicily converts any function or function template into a
/// named declaration.
operator NamedDecl *() const { return Function; }
-
+
/// \brief Retrieve the underlying function or function template.
NamedDecl *get() const { return Function; }
-
- static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
+
+ static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
return AnyFunctionDecl(ND);
}
};
-
+
} // end namespace clang
namespace llvm {
- /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from
+ /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from
/// AnyFunctionDecl to any function or function template declaration.
template<> struct simplify_type<const ::clang::AnyFunctionDecl> {
typedef ::clang::NamedDecl* SimpleType;
@@ -63,26 +68,26 @@ namespace llvm {
};
template<> struct simplify_type< ::clang::AnyFunctionDecl>
: public simplify_type<const ::clang::AnyFunctionDecl> {};
-
+
// Provide PointerLikeTypeTraits for non-cvr pointers.
template<>
class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
public:
static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
- return F.get();
+ return F.get();
}
static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
return ::clang::AnyFunctionDecl::getFromNamedDecl(
static_cast< ::clang::NamedDecl*>(P));
}
-
+
enum { NumLowBitsAvailable = 2 };
};
-
+
} // end namespace llvm
namespace clang {
-
+
/// OverloadedFunctionDecl - An instance of this class represents a
/// set of overloaded functions. All of the functions have the same
/// name and occur within the same scope.
@@ -127,12 +132,64 @@ public:
unsigned size() const { return Functions.size(); }
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
- return D->getKind() == OverloadedFunction;
+ static bool classof(const Decl *D) {
+ return D->getKind() == OverloadedFunction;
}
static bool classof(const OverloadedFunctionDecl *D) { return true; }
};
+/// \brief Provides uniform iteration syntax for an overload set, function,
+/// or function template.
+class OverloadIterator {
+ /// \brief An overloaded function set, function declaration, or
+ /// function template declaration.
+ NamedDecl *D;
+
+ /// \brief If the declaration is an overloaded function set, this is the
+ /// iterator pointing to the current position within that overloaded
+ /// function set.
+ OverloadedFunctionDecl::function_iterator Iter;
+
+public:
+ typedef AnyFunctionDecl value_type;
+ typedef value_type reference;
+ typedef NamedDecl *pointer;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ OverloadIterator() : D(0) { }
+
+ OverloadIterator(FunctionDecl *FD) : D(FD) { }
+ OverloadIterator(FunctionTemplateDecl *FTD)
+ : D(reinterpret_cast<NamedDecl*>(FTD)) { }
+ OverloadIterator(OverloadedFunctionDecl *Ovl)
+ : D(Ovl), Iter(Ovl->function_begin()) { }
+
+ OverloadIterator(NamedDecl *ND);
+
+ reference operator*() const;
+
+ pointer operator->() const { return (**this).get(); }
+
+ OverloadIterator &operator++();
+
+ OverloadIterator operator++(int) {
+ OverloadIterator Temp(*this);
+ ++(*this);
+ return Temp;
+ }
+
+ bool Equals(const OverloadIterator &Other) const;
+};
+
+inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) {
+ return X.Equals(Y);
+}
+
+inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) {
+ return !(X == Y);
+}
+
/// CXXBaseSpecifier - A base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
@@ -162,7 +219,7 @@ class CXXBaseSpecifier {
/// struct (false). This determines the mapping from the access
/// specifier as written in the source code to the access specifier
/// used for semantic analysis.
- bool BaseOfClass : 1;
+ bool BaseOfClass : 1;
/// Access - Access specifier as written in the source code (which
/// may be AS_none). The actual type of data stored here is an
@@ -173,7 +230,7 @@ class CXXBaseSpecifier {
/// BaseType - The type of the base class. This will be a class or
/// struct (or a typedef of such).
QualType BaseType;
-
+
public:
CXXBaseSpecifier() { }
@@ -183,7 +240,7 @@ public:
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
SourceRange getSourceRange() const { return Range; }
-
+
/// isVirtual - Determines whether the base class is a virtual base
/// class (or not).
bool isVirtual() const { return Virtual; }
@@ -193,11 +250,11 @@ public:
/// semantic analysis, so the result can never be AS_none. To
/// retrieve the access specifier as written in the source code, use
/// getAccessSpecifierAsWritten().
- AccessSpecifier getAccessSpecifier() const {
+ AccessSpecifier getAccessSpecifier() const {
if ((AccessSpecifier)Access == AS_none)
return BaseOfClass? AS_private : AS_public;
else
- return (AccessSpecifier)Access;
+ return (AccessSpecifier)Access;
}
/// getAccessSpecifierAsWritten - Retrieves the access specifier as
@@ -218,7 +275,7 @@ public:
/// to deal with C++-specific things.
class CXXRecordDecl : public RecordDecl {
/// UserDeclaredConstructor - True when this class has a
- /// user-declared constructor.
+ /// user-declared constructor.
bool UserDeclaredConstructor : 1;
/// UserDeclaredCopyConstructor - True when this class has a
@@ -239,6 +296,12 @@ class CXXRecordDecl : public RecordDecl {
/// PlainOldData - True when this class is a POD-type.
bool PlainOldData : 1;
+ /// Empty - true when this class is empty for traits purposes, i.e. has no
+ /// data members other than 0-width bit-fields, has no virtual function/base,
+ /// and doesn't inherit from a non-empty class. Doesn't take union-ness into
+ /// account.
+ bool Empty : 1;
+
/// Polymorphic - True when this class is polymorphic, i.e. has at least one
/// virtual member or derives from a polymorphic class.
bool Polymorphic : 1;
@@ -246,12 +309,55 @@ class CXXRecordDecl : public RecordDecl {
/// Abstract - True when this class is abstract, i.e. has at least one
/// pure virtual function, (that can come from a base class).
bool Abstract : 1;
-
- /// HasTrivialConstructor - True when this class has a trivial constructor
+
+ /// HasTrivialConstructor - True when this class has a trivial constructor.
+ ///
+ /// C++ [class.ctor]p5. A constructor is trivial if it is an
+ /// implicitly-declared default constructor and if:
+ /// * its class has no virtual functions and no virtual base classes, and
+ /// * all the direct base classes of its class have trivial constructors, and
+ /// * for all the nonstatic data members of its class that are of class type
+ /// (or array thereof), each such class has a trivial constructor.
bool HasTrivialConstructor : 1;
-
- /// HasTrivialDestructor - True when this class has a trivial destructor
+
+ /// HasTrivialCopyConstructor - True when this class has a trivial copy
+ /// constructor.
+ ///
+ /// C++ [class.copy]p6. A copy constructor for class X is trivial
+ /// if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy constructor, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy constructor;
+ /// otherwise the copy constructor is non-trivial.
+ bool HasTrivialCopyConstructor : 1;
+
+ /// HasTrivialCopyAssignment - True when this class has a trivial copy
+ /// assignment operator.
+ ///
+ /// C++ [class.copy]p11. A copy assignment operator for class X is
+ /// trivial if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy assignment operator, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy assignment
+ /// operator;
+ /// otherwise the copy assignment operator is non-trivial.
+ bool HasTrivialCopyAssignment : 1;
+
+ /// HasTrivialDestructor - True when this class has a trivial destructor.
+ ///
+ /// C++ [class.dtor]p3. A destructor is trivial if it is an
+ /// implicitly-declared destructor and if:
+ /// * all of the direct base classes of its class have trivial destructors
+ /// and
+ /// * for all of the non-static data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial destructor.
bool HasTrivialDestructor : 1;
+
+ /// ComputedVisibleConversions - True when visible conversion functions are
+ /// already computed and are available.
+ bool ComputedVisibleConversions : 1;
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
@@ -260,45 +366,85 @@ class CXXRecordDecl : public RecordDecl {
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
+ /// VBases - direct and indirect virtual base classes of this class.
+ CXXBaseSpecifier *VBases;
+
+ /// NumVBases - The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
- /// CXXConversionDecl.
+ /// CXXConversionDecl.
OverloadedFunctionDecl Conversions;
+ /// VisibleConversions - Overload set containing the conversion functions
+ /// of this C++ class and all those inherited conversion functions that
+ /// are visible in this class. Each of the entries in this overload set is
+ /// a CXXConversionDecl or a FunctionTemplateDecl.
+ OverloadedFunctionDecl VisibleConversions;
+
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
- ///
+ ///
/// For non-templates, this value will be NULL. For record
/// declarations that describe a class template, this will be a
/// pointer to a ClassTemplateDecl. For member
/// classes of class template specializations, this will be the
- /// RecordDecl from which the member class was instantiated.
- llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
+ /// MemberSpecializationInfo referring to the member class that was
+ /// instantiated or specialized.
+ llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
TemplateOrInstantiation;
-
+
+ void getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
+ const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet,
+ const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes);
+ void collectConversionFunctions(
+ llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet);
+
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id);
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL = SourceLocation());
~CXXRecordDecl();
public:
/// base_class_iterator - Iterator that traverses the base classes
- /// of a clas.
+ /// of a class.
typedef CXXBaseSpecifier* base_class_iterator;
/// base_class_const_iterator - Iterator that traverses the base
- /// classes of a clas.
+ /// classes of a class.
typedef const CXXBaseSpecifier* base_class_const_iterator;
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_iterator>
+ reverse_base_class_iterator;
+
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_const_iterator>
+ reverse_base_class_const_iterator;
+
+ virtual CXXRecordDecl *getCanonicalDecl() {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL = SourceLocation(),
CXXRecordDecl* PrevDecl=0,
bool DelayTypeCreation = false);
-
+
virtual void Destroy(ASTContext& C);
-
+
+ bool isDynamicClass() const {
+ return Polymorphic || NumVBases != 0;
+ }
+
/// setBases - Sets the base classes of this struct or class.
void setBases(ASTContext &C,
CXXBaseSpecifier const * const *Bases, unsigned NumBases);
@@ -311,18 +457,78 @@ public:
base_class_const_iterator bases_begin() const { return Bases; }
base_class_iterator bases_end() { return Bases + NumBases; }
base_class_const_iterator bases_end() const { return Bases + NumBases; }
+ reverse_base_class_iterator bases_rbegin() {
+ return reverse_base_class_iterator(bases_end());
+ }
+ reverse_base_class_const_iterator bases_rbegin() const {
+ return reverse_base_class_const_iterator(bases_end());
+ }
+ reverse_base_class_iterator bases_rend() {
+ return reverse_base_class_iterator(bases_begin());
+ }
+ reverse_base_class_const_iterator bases_rend() const {
+ return reverse_base_class_const_iterator(bases_begin());
+ }
+
+ /// getNumVBases - Retrieves the number of virtual base classes of this
+ /// class.
+ unsigned getNumVBases() const { return NumVBases; }
+
+ base_class_iterator vbases_begin() { return VBases; }
+ base_class_const_iterator vbases_begin() const { return VBases; }
+ base_class_iterator vbases_end() { return VBases + NumVBases; }
+ base_class_const_iterator vbases_end() const { return VBases + NumVBases; }
+ reverse_base_class_iterator vbases_rbegin() {
+ return reverse_base_class_iterator(vbases_end());
+ }
+ reverse_base_class_const_iterator vbases_rbegin() const {
+ return reverse_base_class_const_iterator(vbases_end());
+ }
+ reverse_base_class_iterator vbases_rend() {
+ return reverse_base_class_iterator(vbases_begin());
+ }
+ reverse_base_class_const_iterator vbases_rend() const {
+ return reverse_base_class_const_iterator(vbases_begin());
+ }
+
+ /// Iterator access to method members. The method iterator visits
+ /// all method members of the class, including non-instance methods,
+ /// special methods, etc.
+ typedef specific_decl_iterator<CXXMethodDecl> method_iterator;
+
+ /// method_begin - Method begin iterator. Iterates in the order the methods
+ /// were declared.
+ method_iterator method_begin() const {
+ return method_iterator(decls_begin());
+ }
+ /// method_end - Method end iterator.
+ method_iterator method_end() const {
+ return method_iterator(decls_end());
+ }
+
+ /// Iterator access to constructor members.
+ typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator;
+
+ ctor_iterator ctor_begin() const {
+ return ctor_iterator(decls_begin());
+ }
+ ctor_iterator ctor_end() const {
+ return ctor_iterator(decls_end());
+ }
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
/// getCopyConstructor - Returns the copy constructor for this class
- CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
+ CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
unsigned TypeQuals) const;
/// hasConstCopyAssignment - Determines whether this class has a
/// copy assignment operator that accepts a const-qualified argument.
- bool hasConstCopyAssignment(ASTContext &Context) const;
+ /// It returns its decl in MD if found.
+ bool hasConstCopyAssignment(ASTContext &Context,
+ const CXXMethodDecl *&MD) const;
/// addedConstructor - Notify the class that another constructor has
/// been added. This routine helps maintain information about the
@@ -332,7 +538,12 @@ public:
/// hasUserDeclaredConstructor - Whether this class has any
/// user-declared constructors. When true, a default constructor
/// will not be implicitly declared.
- bool hasUserDeclaredConstructor() const { return UserDeclaredConstructor; }
+ bool hasUserDeclaredConstructor() const {
+ assert((isDefinition() ||
+ cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
+ "Incomplete record decl!");
+ return UserDeclaredConstructor;
+ }
/// hasUserDeclaredCopyConstructor - Whether this class has a
/// user-declared copy constructor. When false, a copy constructor
@@ -361,22 +572,43 @@ public:
/// setUserDeclaredDestructor - Set whether this class has a
/// user-declared destructor. If not set by the time the class is
/// fully defined, a destructor will be implicitly declared.
- void setUserDeclaredDestructor(bool UCD) {
- UserDeclaredDestructor = UCD;
+ void setUserDeclaredDestructor(bool UCD) {
+ UserDeclaredDestructor = UCD;
}
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
- OverloadedFunctionDecl *getConversionFunctions() {
- return &Conversions;
+ OverloadedFunctionDecl *getConversionFunctions() {
+ assert((this->isDefinition() ||
+ cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
+ "getConversionFunctions() called on incomplete type");
+ return &Conversions;
}
- const OverloadedFunctionDecl *getConversionFunctions() const {
- return &Conversions;
+ const OverloadedFunctionDecl *getConversionFunctions() const {
+ assert((this->isDefinition() ||
+ cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
+ "getConversionFunctions() called on incomplete type");
+ return &Conversions;
}
+ /// getVisibleConversionFunctions - get all conversion functions visible
+ /// in current class; including conversion function templates.
+ OverloadedFunctionDecl *getVisibleConversionFunctions();
+ /// addVisibleConversionFunction - Add a new conversion function to the
+ /// list of visible conversion functions.
+ void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
+
+ /// \brief Add a new conversion function template to the list of visible
+ /// conversion functions.
+ void addVisibleConversionFunction(FunctionTemplateDecl *ConvDecl);
+
/// addConversionFunction - Add a new conversion function to the
/// list of conversion functions.
- void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl);
+ void addConversionFunction(CXXConversionDecl *ConvDecl);
+
+ /// \brief Add a new conversion function template to the list of conversion
+ /// functions.
+ void addConversionFunction(FunctionTemplateDecl *ConvDecl);
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
@@ -397,6 +629,15 @@ public:
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
void setPOD(bool POD) { PlainOldData = POD; }
+ /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
+ /// means it has a virtual function, virtual base, data member (other than
+ /// 0-width bit-field) or inherits from a non-empty class. Does NOT include
+ /// a check for union-ness.
+ bool isEmpty() const { return Empty; }
+
+ /// Set whether this class is empty (C++0x [meta.unary.prop])
+ void setEmpty(bool Emp) { Empty = Emp; }
+
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return Polymorphic; }
@@ -408,26 +649,42 @@ public:
/// isAbstract - Whether this class is abstract (C++ [class.abstract]),
/// which means that the class contains or inherits a pure virtual function.
bool isAbstract() const { return Abstract; }
-
+
/// setAbstract - Set whether this class is abstract (C++ [class.abstract])
void setAbstract(bool Abs) { Abstract = Abs; }
-
+
// hasTrivialConstructor - Whether this class has a trivial constructor
// (C++ [class.ctor]p5)
bool hasTrivialConstructor() const { return HasTrivialConstructor; }
-
+
// setHasTrivialConstructor - Set whether this class has a trivial constructor
// (C++ [class.ctor]p5)
void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
-
+
+ // hasTrivialCopyConstructor - Whether this class has a trivial copy
+ // constructor (C++ [class.copy]p6)
+ bool hasTrivialCopyConstructor() const { return HasTrivialCopyConstructor; }
+
+ // setHasTrivialCopyConstructor - Set whether this class has a trivial
+ // copy constructor (C++ [class.copy]p6)
+ void setHasTrivialCopyConstructor(bool TC) { HasTrivialCopyConstructor = TC; }
+
+ // hasTrivialCopyAssignment - Whether this class has a trivial copy
+ // assignment operator (C++ [class.copy]p11)
+ bool hasTrivialCopyAssignment() const { return HasTrivialCopyAssignment; }
+
+ // setHasTrivialCopyAssignment - Set whether this class has a
+ // trivial copy assignment operator (C++ [class.copy]p11)
+ void setHasTrivialCopyAssignment(bool TC) { HasTrivialCopyAssignment = TC; }
+
// hasTrivialDestructor - Whether this class has a trivial destructor
// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const { return HasTrivialDestructor; }
-
+
// setHasTrivialDestructor - Set whether this class has a trivial destructor
// (C++ [class.dtor]p3)
void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; }
-
+
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
@@ -447,15 +704,17 @@ public:
/// the CXXRecordDecl X<T>::A. When a complete definition of
/// X<int>::A is required, it will be instantiated from the
/// declaration returned by getInstantiatedFromMemberClass().
- CXXRecordDecl *getInstantiatedFromMemberClass() const {
- return TemplateOrInstantiation.dyn_cast<CXXRecordDecl*>();
- }
-
+ CXXRecordDecl *getInstantiatedFromMemberClass() const;
+
+ /// \brief If this class is an instantiation of a member class of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
/// \brief Specify that this record is an instantiation of the
/// member class RD.
- void setInstantiationOfMemberClass(CXXRecordDecl *RD) {
- TemplateOrInstantiation = RD;
- }
+ void setInstantiationOfMemberClass(CXXRecordDecl *RD,
+ TemplateSpecializationKind TSK);
/// \brief Retrieves the class template that is described by this
/// class declaration.
@@ -476,34 +735,150 @@ public:
TemplateOrInstantiation = Template;
}
+ /// \brief Determine whether this particular class is a specialization or
+ /// instantiation of a class template or member class of a class template,
+ /// and how it was instantiated or specialized.
+ TemplateSpecializationKind getTemplateSpecializationKind();
+
+ /// \brief Set the kind of specialization or template instantiation this is.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+
/// getDefaultConstructor - Returns the default constructor for this class
CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
-
+
/// getDestructor - Returns the destructor decl for this class.
const CXXDestructorDecl *getDestructor(ASTContext &Context);
-
+
/// isLocalClass - If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
return RD->isLocalClass();
-
+
return dyn_cast<FunctionDecl>(getDeclContext());
}
+
+ /// \brief Determine whether this class is derived from the class \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ bool isDerivedFrom(CXXRecordDecl *Base);
+
+ /// \brief Determine whether this class is derived from the type \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \param Paths will contain the paths taken from the current class to the
+ /// given \p Base class.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ ///
+ /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
+ /// tangling input and output in \p Paths
+ bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths);
+
+ /// \brief Function type used by lookupInBases() to determine whether a
+ /// specific base class subobject matches the lookup criteria.
+ ///
+ /// \param Specifier the base-class specifier that describes the inheritance
+ /// from the base class we are trying to match.
+ ///
+ /// \param Path the current path, from the most-derived class down to the
+ /// base named by the \p Specifier.
+ ///
+ /// \param UserData a single pointer to user-specified data, provided to
+ /// lookupInBases().
+ ///
+ /// \returns true if this base matched the search criteria, false otherwise.
+ typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
+
+ /// \brief Look for entities within the base classes of this C++ class,
+ /// transitively searching all base class subobjects.
+ ///
+ /// This routine uses the callback function \p BaseMatches to find base
+ /// classes meeting some search criteria, walking all base class subobjects
+ /// and populating the given \p Paths structure with the paths through the
+ /// inheritance hierarchy that resulted in a match. On a successful search,
+ /// the \p Paths structure can be queried to retrieve the matching paths and
+ /// to determine if there were any ambiguities.
+ ///
+ /// \param BaseMatches callback function used to determine whether a given
+ /// base matches the user-defined search criteria.
+ ///
+ /// \param UserData user data pointer that will be provided to \p BaseMatches.
+ ///
+ /// \param Paths used to record the paths from this class to its base class
+ /// subobjects that match the search criteria.
+ ///
+ /// \returns true if there exists any path from this class to a base class
+ /// subobject that matches the search criteria.
+ bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ CXXBasePaths &Paths);
+
+ /// \brief Base-class lookup callback that determines whether the given
+ /// base class specifier refers to a specific class declaration.
+ ///
+ /// This callback can be used with \c lookupInBases() to determine whether
+ /// a given derived class has is a base class subobject of a particular type.
+ /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// base class that we are searching for.
+ static bool FindBaseClass(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ void *BaseRecord);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a tag with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find tag members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindTagMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindOrdinaryMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name that can be used in a nested-name-specifier.
+ ///
+ /// This callback can be used with \c lookupInBases() to find membes of
+ /// the given name within a C++ class hierarchy that can occur within
+ /// nested-name-specifiers.
+ static bool FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
- static bool classof(const Decl *D) {
- return D->getKind() == CXXRecord ||
+ static bool classof(const Decl *D) {
+ return D->getKind() == CXXRecord ||
D->getKind() == ClassTemplateSpecialization ||
- D->getKind() == ClassTemplatePartialSpecialization;
+ D->getKind() == ClassTemplatePartialSpecialization;
}
static bool classof(const CXXRecordDecl *D) { return true; }
- static bool classof(const ClassTemplateSpecializationDecl *D) {
- return true;
+ static bool classof(const ClassTemplateSpecializationDecl *D) {
+ return true;
}
};
@@ -512,42 +887,60 @@ public:
class CXXMethodDecl : public FunctionDecl {
protected:
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T,
+ DeclarationName N, QualType T, DeclaratorInfo *DInfo,
bool isStatic, bool isInline)
- : FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None),
+ : FunctionDecl(DK, RD, L, N, T, DInfo, (isStatic ? Static : None),
isInline) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
- QualType T, bool isStatic = false,
+ QualType T, DeclaratorInfo *DInfo,
+ bool isStatic = false,
bool isInline = false);
-
+
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
- bool isVirtual() const {
- return isVirtualAsWritten() ||
- (begin_overridden_methods() != end_overridden_methods());
- }
+ bool isVirtual() const {
+ CXXMethodDecl *CD =
+ cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
- ///
- void addOverriddenMethod(const CXXMethodDecl *MD);
+ if (CD->isVirtualAsWritten())
+ return true;
+
+ return (CD->begin_overridden_methods() != CD->end_overridden_methods());
+ }
- typedef const CXXMethodDecl ** method_iterator;
+ /// \brief Determine whether this is a usual deallocation function
+ /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
+ /// delete or delete[] operator with a particular signature.
+ bool isUsualDeallocationFunction() const;
+ const CXXMethodDecl *getCanonicalDecl() const {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ CXXMethodDecl *getCanonicalDecl() {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+
+ ///
+ void addOverriddenMethod(const CXXMethodDecl *MD);
+
+ typedef const CXXMethodDecl ** method_iterator;
+
method_iterator begin_overridden_methods() const;
method_iterator end_overridden_methods() const;
-
+
/// getParent - Returns the parent of this method declaration, which
/// is the class in which this method is defined.
- const CXXRecordDecl *getParent() const {
- return cast<CXXRecordDecl>(FunctionDecl::getParent());
+ const CXXRecordDecl *getParent() const {
+ return cast<CXXRecordDecl>(FunctionDecl::getParent());
}
-
+
/// getParent - Returns the parent of this method declaration, which
/// is the class in which this method is defined.
- CXXRecordDecl *getParent() {
+ CXXRecordDecl *getParent() {
return const_cast<CXXRecordDecl *>(
cast<CXXRecordDecl>(FunctionDecl::getParent()));
}
@@ -557,11 +950,11 @@ public:
QualType getThisType(ASTContext &C) const;
unsigned getTypeQualifiers() const {
- return getType()->getAsFunctionProtoType()->getTypeQuals();
+ return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion;
}
static bool classof(const CXXMethodDecl *D) { return true; }
@@ -589,38 +982,63 @@ class CXXBaseOrMemberInitializer {
uintptr_t BaseOrMember;
/// Args - The arguments used to initialize the base or member.
- Expr **Args;
+ Stmt **Args;
unsigned NumArgs;
-
+
+ /// \brief Stores either the constructor to call to initialize this base or
+ /// member (a CXXConstructorDecl pointer), or stores the anonymous union of
+ /// which the initialized value is a member.
+ ///
+ /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's
+ /// anonymous union data member, this field holds the FieldDecl for the
+ /// member of the anonymous union being initialized.
+ /// @code
+ /// struct X {
+ /// X() : au_i1(123) {}
+ /// union {
+ /// int au_i1;
+ /// float au_f1;
+ /// };
+ /// };
+ /// @endcode
+ /// In above example, BaseOrMember holds the field decl. for anonymous union
+ /// and AnonUnionMember holds field decl for au_i1.
+ llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion;
+
/// IdLoc - Location of the id in ctor-initializer list.
SourceLocation IdLoc;
+ /// RParenLoc - Location of the right paren of the ctor-initializer.
+ SourceLocation RParenLoc;
+
public:
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
- explicit
+ explicit
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
- SourceLocation L);
+ CXXConstructorDecl *C,
+ SourceLocation L, SourceLocation R);
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
- explicit
+ explicit
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
- SourceLocation L);
+ CXXConstructorDecl *C,
+ SourceLocation L, SourceLocation R);
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
~CXXBaseOrMemberInitializer();
/// arg_iterator - Iterates through the member initialization
/// arguments.
- typedef Expr **arg_iterator;
+ typedef ExprIterator arg_iterator;
/// arg_const_iterator - Iterates through the member initialization
/// arguments.
- typedef Expr * const * arg_const_iterator;
+ typedef ConstExprIterator const_arg_iterator;
/// getBaseOrMember - get the generic 'member' representing either the field
/// or a base class.
void* getBaseOrMember() const { return reinterpret_cast<void*>(BaseOrMember); }
-
+
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; }
@@ -633,8 +1051,8 @@ public:
/// type used to specify the initializer. The resulting type will be
/// a class type or a typedef of a class type. If this is not a base
/// class initializer, returns NULL.
- Type *getBaseClass() {
- if (isBaseInitializer())
+ Type *getBaseClass() {
+ if (isBaseInitializer())
return reinterpret_cast<Type*>(BaseOrMember & ~0x01);
else
return 0;
@@ -644,8 +1062,8 @@ public:
/// type used to specify the initializer. The resulting type will be
/// a class type or a typedef of a class type. If this is not a base
/// class initializer, returns NULL.
- const Type *getBaseClass() const {
- if (isBaseInitializer())
+ const Type *getBaseClass() const {
+ if (isBaseInitializer())
return reinterpret_cast<const Type*>(BaseOrMember & ~0x01);
else
return 0;
@@ -654,24 +1072,40 @@ public:
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
- FieldDecl *getMember() {
+ FieldDecl *getMember() {
if (isMemberInitializer())
- return reinterpret_cast<FieldDecl *>(BaseOrMember);
+ return reinterpret_cast<FieldDecl *>(BaseOrMember);
else
return 0;
}
+ void setMember(FieldDecl * anonUnionField) {
+ BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField);
+ }
+
+ FieldDecl *getAnonUnionMember() const {
+ return CtorOrAnonUnion.dyn_cast<FieldDecl *>();
+ }
+ void setAnonUnionMember(FieldDecl *anonMember) {
+ CtorOrAnonUnion = anonMember;
+ }
+
+ const CXXConstructorDecl *getConstructor() const {
+ return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>();
+ }
+
SourceLocation getSourceLocation() const { return IdLoc; }
-
- /// begin() - Retrieve an iterator to the first initializer argument.
- arg_iterator begin() { return Args; }
- /// begin() - Retrieve an iterator to the first initializer argument.
- arg_const_iterator begin() const { return Args; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
- /// end() - Retrieve an iterator past the last initializer argument.
- arg_iterator end() { return Args + NumArgs; }
- /// end() - Retrieve an iterator past the last initializer argument.
- arg_const_iterator end() const { return Args + NumArgs; }
+ /// arg_begin() - Retrieve an iterator to the first initializer argument.
+ arg_iterator arg_begin() { return Args; }
+ /// arg_begin() - Retrieve an iterator to the first initializer argument.
+ const_arg_iterator const_arg_begin() const { return Args; }
+
+ /// arg_end() - Retrieve an iterator past the last initializer argument.
+ arg_iterator arg_end() { return Args + NumArgs; }
+ /// arg_end() - Retrieve an iterator past the last initializer argument.
+ const_arg_iterator const_arg_end() const { return Args + NumArgs; }
/// getNumArgs - Determine the number of arguments used to
/// initialize the member or base.
@@ -680,7 +1114,7 @@ public:
/// CXXConstructorDecl - Represents a C++ constructor within a
/// class. For example:
-///
+///
/// @code
/// class X {
/// public:
@@ -698,82 +1132,86 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// explicitly defaulted (i.e., defined with " = default") will have
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
-
+
/// Support for base and member initializers.
- /// BaseOrMemberInitializers - The arguments used to initialize the base
+ /// BaseOrMemberInitializers - The arguments used to initialize the base
/// or member.
CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
unsigned NumBaseOrMemberInitializers;
-
+
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T,
+ DeclarationName N, QualType T, DeclaratorInfo *DInfo,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
+ : CXXMethodDecl(CXXConstructor, RD, L, N, T, DInfo, false, isInline),
Explicit(isExplicit), ImplicitlyDefined(false),
- BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
+ BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
virtual void Destroy(ASTContext& C);
-
+
public:
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
- QualType T, bool isExplicit,
+ QualType T, DeclaratorInfo *DInfo,
+ bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
- /// isExplicit - Whether this constructor was marked "explicit" or not.
+ /// isExplicit - Whether this constructor was marked "explicit" or not.
bool isExplicit() const { return Explicit; }
/// isImplicitlyDefined - Whether this constructor was implicitly
/// defined. If false, then this constructor was defined by the
/// user. This operation can only be invoked if the constructor has
/// already been defined.
- bool isImplicitlyDefined(ASTContext &C) const {
- assert(isThisDeclarationADefinition() &&
+ bool isImplicitlyDefined(ASTContext &C) const {
+ assert(isThisDeclarationADefinition() &&
"Can only get the implicit-definition flag once the "
"constructor has been defined");
- return ImplicitlyDefined;
+ return ImplicitlyDefined;
}
/// setImplicitlyDefined - Set whether this constructor was
/// implicitly defined or not.
- void setImplicitlyDefined(bool ID) {
- assert(isThisDeclarationADefinition() &&
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
"Can only set the implicit-definition flag once the constructor "
"has been defined");
- ImplicitlyDefined = ID;
+ ImplicitlyDefined = ID;
}
-
+
/// init_iterator - Iterates through the member/base initializer list.
typedef CXXBaseOrMemberInitializer **init_iterator;
-
+
/// init_const_iterator - Iterates through the memberbase initializer list.
typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
-
- /// begin() - Retrieve an iterator to the first initializer.
- init_iterator begin() { return BaseOrMemberInitializers; }
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() { return BaseOrMemberInitializers; }
/// begin() - Retrieve an iterator to the first initializer.
- init_const_iterator begin() const { return BaseOrMemberInitializers; }
-
- /// end() - Retrieve an iterator past the last initializer.
- init_iterator end() {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ init_const_iterator init_begin() const { return BaseOrMemberInitializers; }
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
}
/// end() - Retrieve an iterator past the last initializer.
- init_const_iterator end() const {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ init_const_iterator init_end() const {
+ return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
}
-
+
/// getNumArgs - Determine the number of arguments used to
/// initialize the member or base.
- unsigned getNumBaseOrMemberInitializers() const {
- return NumBaseOrMemberInitializers;
+ unsigned getNumBaseOrMemberInitializers() const {
+ return NumBaseOrMemberInitializers;
+ }
+
+ void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) {
+ NumBaseOrMemberInitializers = numBaseOrMemberInitializers;
+ }
+
+ void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) {
+ BaseOrMemberInitializers = initializers;
}
-
- void setBaseOrMemberInitializers(ASTContext &C,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers);
-
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
/// default-initialize a class of this type.
@@ -804,10 +1242,10 @@ public:
/// isConvertingConstructor - Whether this constructor is a
/// converting constructor (C++ [class.conv.ctor]), which can be
/// used for user-defined conversions.
- bool isConvertingConstructor() const;
+ bool isConvertingConstructor(bool AllowExplicit) const;
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() == CXXConstructor;
}
static bool classof(const CXXConstructorDecl *D) { return true; }
@@ -815,7 +1253,7 @@ public:
/// CXXDestructorDecl - Represents a C++ destructor within a
/// class. For example:
-///
+///
/// @code
/// class X {
/// public:
@@ -823,6 +1261,13 @@ public:
/// };
/// @endcode
class CXXDestructorDecl : public CXXMethodDecl {
+public:
+ enum KindOfObjectToDestroy {
+ VBASE = 0x1,
+ DRCTNONVBASE = 0x2,
+ ANYBASE = 0x3
+ };
+private:
/// ImplicitlyDefined - Whether this destructor was implicitly
/// defined by the compiler. When false, the destructor was defined
/// by the user. In C++03, this flag will have the same value as
@@ -831,40 +1276,141 @@ class CXXDestructorDecl : public CXXMethodDecl {
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
+ /// Support for base and member destruction.
+ /// BaseOrMemberDestructions - The arguments used to destruct the base
+ /// or member. Each uintptr_t value represents one of base classes (either
+ /// virtual or direct non-virtual base), or non-static data member
+ /// to be destroyed. The low two bits encode the kind of object
+ /// being destroyed.
+ uintptr_t *BaseOrMemberDestructions;
+ unsigned NumBaseOrMemberDestructions;
+
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline),
- ImplicitlyDefined(false) {
+ : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline),
+ ImplicitlyDefined(false),
+ BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) {
setImplicit(isImplicitlyDeclared);
}
+ virtual void Destroy(ASTContext& C);
public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
- QualType T, bool isInline,
+ QualType T, bool isInline,
bool isImplicitlyDeclared);
/// isImplicitlyDefined - Whether this destructor was implicitly
/// defined. If false, then this destructor was defined by the
/// user. This operation can only be invoked if the destructor has
/// already been defined.
- bool isImplicitlyDefined() const {
- assert(isThisDeclarationADefinition() &&
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
"Can only get the implicit-definition flag once the destructor has been defined");
- return ImplicitlyDefined;
+ return ImplicitlyDefined;
}
/// setImplicitlyDefined - Set whether this destructor was
/// implicitly defined or not.
- void setImplicitlyDefined(bool ID) {
- assert(isThisDeclarationADefinition() &&
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
"Can only set the implicit-definition flag once the destructor has been defined");
- ImplicitlyDefined = ID;
+ ImplicitlyDefined = ID;
+ }
+
+ /// destr_iterator - Iterates through the member/base destruction list.
+
+ /// destr_const_iterator - Iterates through the member/base destruction list.
+ typedef uintptr_t const destr_const_iterator;
+
+ /// destr_begin() - Retrieve an iterator to the first destructed member/base.
+ uintptr_t* destr_begin() {
+ return BaseOrMemberDestructions;
+ }
+ /// destr_begin() - Retrieve an iterator to the first destructed member/base.
+ uintptr_t* destr_begin() const {
+ return BaseOrMemberDestructions;
+ }
+
+ /// destr_end() - Retrieve an iterator past the last destructed member/base.
+ uintptr_t* destr_end() {
+ return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
+ }
+ /// destr_end() - Retrieve an iterator past the last destructed member/base.
+ uintptr_t* destr_end() const {
+ return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
+ }
+
+ /// getNumBaseOrMemberDestructions - Number of base and non-static members
+ /// to destroy.
+ unsigned getNumBaseOrMemberDestructions() const {
+ return NumBaseOrMemberDestructions;
+ }
+
+ /// setNumBaseOrMemberDestructions - Set number of base and non-static members
+ /// to destroy.
+ void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) {
+ NumBaseOrMemberDestructions = numBaseOrMemberDestructions;
+ }
+
+ /// getBaseOrMemberToDestroy - get the generic 'member' representing either
+ /// the field or a base class.
+ uintptr_t* getBaseOrMemberToDestroy() const {
+ return BaseOrMemberDestructions;
+ }
+
+ /// setBaseOrMemberToDestroy - set the generic 'member' representing either
+ /// the field or a base class.
+ void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) {
+ BaseOrMemberDestructions = baseOrMemberDestructions;
+ }
+
+ /// isVbaseToDestroy - returns true, if object is virtual base.
+ bool isVbaseToDestroy(uintptr_t Vbase) const {
+ return (Vbase & VBASE) != 0;
+ }
+ /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual
+ /// base.
+ bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const {
+ return (DrctNonVbase & DRCTNONVBASE) != 0;
+ }
+ /// isAnyBaseToDestroy - returns true, if object is any base (virtual or
+ /// direct non-virtual)
+ bool isAnyBaseToDestroy(uintptr_t AnyBase) const {
+ return (AnyBase & ANYBASE) != 0;
+ }
+ /// isMemberToDestroy - returns true if object is a non-static data member.
+ bool isMemberToDestroy(uintptr_t Member) const {
+ return (Member & ANYBASE) == 0;
+ }
+ /// getAnyBaseClassToDestroy - Get the type for the given base class object.
+ Type *getAnyBaseClassToDestroy(uintptr_t Base) const {
+ if (isAnyBaseToDestroy(Base))
+ return reinterpret_cast<Type*>(Base & ~0x03);
+ return 0;
+ }
+ /// getMemberToDestroy - Get the member for the given object.
+ FieldDecl *getMemberToDestroy(uintptr_t Member) const {
+ if (isMemberToDestroy(Member))
+ return reinterpret_cast<FieldDecl *>(Member);
+ return 0;
+ }
+ /// getVbaseClassToDestroy - Get the virtual base.
+ Type *getVbaseClassToDestroy(uintptr_t Vbase) const {
+ if (isVbaseToDestroy(Vbase))
+ return reinterpret_cast<Type*>(Vbase & ~0x01);
+ return 0;
+ }
+ /// getDirectNonVBaseClassToDestroy - Get the virtual base.
+ Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const {
+ if (isDirectNonVBaseToDestroy(Base))
+ return reinterpret_cast<Type*>(Base & ~0x02);
+ return 0;
}
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() == CXXDestructor;
}
static bool classof(const CXXDestructorDecl *D) { return true; }
@@ -872,7 +1418,7 @@ public:
/// CXXConversionDecl - Represents a C++ conversion function within a
/// class. For example:
-///
+///
/// @code
/// class X {
/// public:
@@ -886,16 +1432,16 @@ class CXXConversionDecl : public CXXMethodDecl {
bool Explicit : 1;
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T,
+ DeclarationName N, QualType T, DeclaratorInfo *DInfo,
bool isInline, bool isExplicit)
- : CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline),
+ : CXXMethodDecl(CXXConversion, RD, L, N, T, DInfo, false, isInline),
Explicit(isExplicit) { }
public:
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
- QualType T, bool isInline,
- bool isExplicit);
+ QualType T, DeclaratorInfo *DInfo,
+ bool isInline, bool isExplicit);
/// isExplicit - Whether this is an explicit conversion operator
/// (C++0x only). Explicit conversion operators are only considered
@@ -904,17 +1450,81 @@ public:
/// getConversionType - Returns the type that this conversion
/// function is converting to.
- QualType getConversionType() const {
- return getType()->getAsFunctionType()->getResultType();
+ QualType getConversionType() const {
+ return getType()->getAs<FunctionType>()->getResultType();
}
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() == CXXConversion;
}
static bool classof(const CXXConversionDecl *D) { return true; }
};
+/// FriendDecl - Represents the declaration of a friend entity,
+/// which can be a function, a type, or a templated function or type.
+// For example:
+///
+/// @code
+/// template <typename T> class A {
+/// friend int foo(T);
+/// friend class B;
+/// friend T; // only in C++0x
+/// template <typename U> friend class C;
+/// template <typename U> friend A& operator+=(A&, const U&) { ... }
+/// };
+/// @endcode
+///
+/// The semantic context of a friend decl is its declaring class.
+class FriendDecl : public Decl {
+public:
+ typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
+
+private:
+ // The declaration that's a friend of this class.
+ FriendUnion Friend;
+
+ // Location of the 'friend' specifier.
+ SourceLocation FriendLoc;
+
+ FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
+ SourceLocation FriendL)
+ : Decl(Decl::Friend, DC, L),
+ Friend(Friend),
+ FriendLoc(FriendL) {
+ }
+
+public:
+ static FriendDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, FriendUnion Friend_,
+ SourceLocation FriendL);
+
+ /// If this friend declaration names an (untemplated but
+ /// possibly dependent) type, return the type; otherwise
+ /// return null. This is used only for C++0x's unelaborated
+ /// friend type declarations.
+ Type *getFriendType() const {
+ return Friend.dyn_cast<Type*>();
+ }
+
+ /// If this friend declaration doesn't name an unelaborated
+ /// type, return the inner declaration.
+ NamedDecl *getFriendDecl() const {
+ return Friend.dyn_cast<NamedDecl*>();
+ }
+
+ /// Retrieves the location of the 'friend' keyword.
+ SourceLocation getFriendLoc() const {
+ return FriendLoc;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::Friend;
+ }
+ static bool classof(const FriendDecl *D) { return true; }
+};
+
/// LinkageSpecDecl - This represents a linkage specification. For example:
/// extern "C" void foo();
///
@@ -934,14 +1544,14 @@ private:
/// HadBraces - Whether this linkage specification had curly braces or not.
bool HadBraces : 1;
- LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
+ LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
bool Braces)
- : Decl(LinkageSpec, DC, L),
+ : Decl(LinkageSpec, DC, L),
DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
public:
- static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, LanguageIDs Lang,
+ static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, LanguageIDs Lang,
bool Braces);
LanguageIDs getLanguage() const { return Language; }
@@ -1008,8 +1618,8 @@ class UsingDirectiveDecl : public NamedDecl {
NamespaceDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(Decl::UsingDirective, DC, L, getName()),
- NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), IdentLoc(IdentLoc),
+ NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc),
NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0),
CommonAncestor(CommonAncestor) {
}
@@ -1074,20 +1684,20 @@ class NamespaceAliasDecl : public NamedDecl {
/// \brief The nested-name-specifier that precedes the namespace
/// name, if any.
NestedNameSpecifier *Qualifier;
-
+
/// IdentLoc - Location of namespace identifier.
SourceLocation IdentLoc;
-
- /// Namespace - The Decl that this alias points to. Can either be a
+
+ /// Namespace - The Decl that this alias points to. Can either be a
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
-
- NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
- SourceLocation AliasLoc, IdentifierInfo *Alias,
+
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, NamedDecl *Namespace)
- : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
+ : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
QualifierRange(QualifierRange), Qualifier(Qualifier),
IdentLoc(IdentLoc), Namespace(Namespace) { }
@@ -1106,7 +1716,7 @@ public:
return cast<NamespaceDecl>(Namespace);
}
-
+
const NamespaceDecl *getNamespace() const {
return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
}
@@ -1115,14 +1725,14 @@ public:
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; }
- static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceLocation AliasLoc,
- IdentifierInfo *Alias,
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
- SourceLocation IdentLoc,
+ SourceLocation IdentLoc,
NamedDecl *Namespace);
-
+
static bool classof(const Decl *D) {
return D->getKind() == Decl::NamespaceAlias;
}
@@ -1132,20 +1742,23 @@ public:
/// UsingDecl - Represents a C++ using-declaration. For example:
/// using someNameSpace::someIdentifier;
class UsingDecl : public NamedDecl {
-
/// \brief The source range that covers the nested-name-specifier
/// preceding the declaration name.
SourceRange NestedNameRange;
+
/// \brief The source location of the target declaration name.
SourceLocation TargetNameLocation;
+
/// \brief The source location of the "using" location itself.
SourceLocation UsingLocation;
+
/// \brief Target declaration.
NamedDecl* TargetDecl;
- /// \brief Target declaration.
+
+ /// \brief Target nested name specifier.
NestedNameSpecifier* TargetNestedNameDecl;
- // Had 'typename' keyword.
+ // \brief Has 'typename' keyword.
bool IsTypeName;
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
@@ -1154,7 +1767,7 @@ class UsingDecl : public NamedDecl {
: NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
NestedNameRange(NNR), TargetNameLocation(TargetNL),
UsingLocation(UL), TargetDecl(Target),
- TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
+ TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
}
@@ -1162,23 +1775,23 @@ public:
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
SourceRange getNestedNameRange() { return NestedNameRange; }
-
+
/// \brief Returns the source location of the target declaration name.
SourceLocation getTargetNameLocation() { return TargetNameLocation; }
-
+
/// \brief Returns the source location of the "using" location itself.
SourceLocation getUsingLocation() { return UsingLocation; }
-
+
/// \brief getTargetDecl - Returns target specified by using-decl.
NamedDecl *getTargetDecl() { return TargetDecl; }
const NamedDecl *getTargetDecl() const { return TargetDecl; }
-
+
/// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameDecl() {
- return TargetNestedNameDecl;
+ NestedNameSpecifier* getTargetNestedNameDecl() {
+ return TargetNestedNameDecl;
}
-
- /// isTypeName - Return true if using decl had 'typename'.
+
+ /// isTypeName - Return true if using decl has 'typename'.
bool isTypeName() const { return IsTypeName; }
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1191,27 +1804,85 @@ public:
}
static bool classof(const UsingDecl *D) { return true; }
};
-
+
+/// UnresolvedUsingDecl - Represents a using declaration whose name can not
+/// yet be resolved.
+class UnresolvedUsingDecl : public NamedDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the target declaration name.
+ SourceLocation TargetNameLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ DeclarationName TargetName;
+
+ // \brief Has 'typename' keyword.
+ bool IsTypeName;
+
+ UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName,
+ bool IsTypeNameArg)
+ : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName),
+ TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc),
+ TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName),
+ IsTypeName(IsTypeNameArg) { }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Returns the source location of the target declaration name.
+ SourceLocation getTargetNameLocation() const { return TargetNameLocation; }
+
+ /// \brief Returns the source location of the target declaration name.
+ DeclarationName getTargetName() const { return TargetName; }
+
+ bool isTypeName() const { return IsTypeName; }
+
+ static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName,
+ bool IsTypeNameArg);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::UnresolvedUsing;
+ }
+ static bool classof(const UnresolvedUsingDecl *D) { return true; }
+};
+
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
class StaticAssertDecl : public Decl {
Expr *AssertExpr;
StringLiteral *Message;
- StaticAssertDecl(DeclContext *DC, SourceLocation L,
+ StaticAssertDecl(DeclContext *DC, SourceLocation L,
Expr *assertexpr, StringLiteral *message)
: Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
-
+
public:
static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, Expr *AssertExpr,
StringLiteral *Message);
-
+
Expr *getAssertExpr() { return AssertExpr; }
const Expr *getAssertExpr() const { return AssertExpr; }
-
+
StringLiteral *getMessage() { return Message; }
const StringLiteral *getMessage() const { return Message; }
-
+
virtual ~StaticAssertDecl();
virtual void Destroy(ASTContext& C);
@@ -1225,7 +1896,7 @@ public:
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
AccessSpecifier AS);
-
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 6c1231c0a73d..d9e40d478907 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -57,13 +57,13 @@ public:
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
}
-
+
~StoredDeclsList() {
// If this is a vector-form, free the vector.
if (VectorTy *Vector = getAsVector())
delete Vector;
}
-
+
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
if (VectorTy *Vector = getAsVector())
delete Vector;
@@ -74,9 +74,9 @@ public:
}
return *this;
}
-
+
bool isNull() const { return (Data & ~0x03) == 0; }
-
+
NamedDecl *getAsDecl() const {
if ((Data & 0x03) != DK_Decl)
return 0;
@@ -135,27 +135,27 @@ public:
DeclContext::lookup_result getLookupResult(ASTContext &Context) {
if (isNull())
return DeclContext::lookup_result(0, 0);
-
+
if (hasDeclarationIDs())
materializeDecls(Context);
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
-
+
// Data is a raw pointer to a NamedDecl*, return it.
void *Ptr = &Data;
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
}
-
+
assert(getAsVector() && "Must have a vector at this point");
VectorTy &Vector = *getAsVector();
-
+
// Otherwise, we have a range result.
- return DeclContext::lookup_result((NamedDecl **)&Vector[0],
+ return DeclContext::lookup_result((NamedDecl **)&Vector[0],
(NamedDecl **)&Vector[0]+Vector.size());
}
-
+
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
@@ -169,7 +169,7 @@ public:
setOnlyValue(D);
return true;
}
-
+
// Determine if this declaration is actually a redeclaration.
VectorTy &Vec = *getAsVector();
for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
@@ -183,10 +183,10 @@ public:
return false;
}
-
+
/// AddSubsequentDecl - This is called on the second and later decl when it is
/// not a redeclaration to merge it into the appropriate place in our list.
- ///
+ ///
void AddSubsequentDecl(NamedDecl *D) {
assert(!hasDeclarationIDs() && "Must materialize before adding decls");
@@ -197,7 +197,7 @@ public:
VT->push_back(reinterpret_cast<uintptr_t>(OldD));
Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
}
-
+
VectorTy &Vec = *getAsVector();
if (isa<UsingDirectiveDecl>(D) ||
D->getIdentifierNamespace() == Decl::IDNS_Tag)
@@ -217,4 +217,4 @@ typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
} // end namespace clang
-#endif
+#endif
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 15a8adef8e57..790ea3ca0662 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -18,7 +18,7 @@
#include <cassert>
namespace clang {
-
+
class ASTContext;
class Decl;
class DeclGroup;
@@ -27,7 +27,7 @@ class DeclGroupIterator;
class DeclGroup {
// FIXME: Include a TypeSpecifier object.
unsigned NumDecls;
-
+
private:
DeclGroup() : NumDecls(0) {}
DeclGroup(unsigned numdecls, Decl** decls);
@@ -38,34 +38,34 @@ public:
unsigned size() const { return NumDecls; }
- Decl*& operator[](unsigned i) {
+ Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
return *((Decl**) (this+1));
}
-
- Decl* const& operator[](unsigned i) const {
+
+ Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
return *((Decl* const*) (this+1));
}
};
-
+
class DeclGroupRef {
// Note this is not a PointerIntPair because we need the address of the
// non-group case to be valid as a Decl** for iteration.
- enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
+ enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
Decl* D;
Kind getKind() const {
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
- }
-
-public:
+ }
+
+public:
DeclGroupRef() : D(0) {}
-
+
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
-
+
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
if (NumDecls == 0)
return DeclGroupRef();
@@ -73,10 +73,10 @@ public:
return DeclGroupRef(Decls[0]);
return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
}
-
+
typedef Decl** iterator;
typedef Decl* const * const_iterator;
-
+
bool isNull() const { return D == 0; }
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
@@ -88,7 +88,7 @@ public:
const Decl *getSingleDecl() const {
return const_cast<DeclGroupRef*>(this)->getSingleDecl();
}
-
+
DeclGroup &getDeclGroup() {
assert(isDeclGroup() && "Isn't a declgroup");
return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
@@ -96,7 +96,7 @@ public:
const DeclGroup &getDeclGroup() const {
return const_cast<DeclGroupRef*>(this)->getDeclGroup();
}
-
+
iterator begin() {
if (isSingleDecl())
return D ? &D : 0;
@@ -109,13 +109,13 @@ public:
DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
-
+
const_iterator begin() const {
if (isSingleDecl())
return D ? &D : 0;
return &getDeclGroup()[0];
}
-
+
const_iterator end() const {
if (isSingleDecl())
return D ? &D+1 : 0;
@@ -130,7 +130,7 @@ public:
return X;
}
};
-
+
} // end clang namespace
namespace llvm {
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
index 1e4440357b65..79a0d368288c 100644
--- a/include/clang/AST/DeclNodes.def
+++ b/include/clang/AST/DeclNodes.def
@@ -91,39 +91,43 @@ ABSTRACT_DECL(Named, Decl)
DECL(TemplateTypeParm, TypeDecl)
ABSTRACT_DECL(Value, NamedDecl)
DECL(EnumConstant, ValueDecl)
- DECL(Function, ValueDecl)
- DECL(CXXMethod, FunctionDecl)
- DECL(CXXConstructor, CXXMethodDecl)
- DECL(CXXDestructor, CXXMethodDecl)
- DECL(CXXConversion, CXXMethodDecl)
- DECL(Field, ValueDecl)
- DECL(ObjCIvar, FieldDecl)
- DECL(ObjCAtDefsField, FieldDecl)
- DECL(Var, ValueDecl)
- DECL(ImplicitParam, VarDecl)
- DECL(ParmVar, VarDecl)
- DECL(OriginalParmVar, ParmVarDecl)
- DECL(NonTypeTemplateParm, VarDecl)
+ ABSTRACT_DECL(Declarator, ValueDecl)
+ DECL(Function, DeclaratorDecl)
+ DECL(CXXMethod, FunctionDecl)
+ DECL(CXXConstructor, CXXMethodDecl)
+ DECL(CXXDestructor, CXXMethodDecl)
+ DECL(CXXConversion, CXXMethodDecl)
+ DECL(Field, DeclaratorDecl)
+ DECL(ObjCIvar, FieldDecl)
+ DECL(ObjCAtDefsField, FieldDecl)
+ DECL(Var, DeclaratorDecl)
+ DECL(ImplicitParam, VarDecl)
+ DECL(ParmVar, VarDecl)
+ DECL(OriginalParmVar, ParmVarDecl)
+ DECL(NonTypeTemplateParm, VarDecl)
DECL(Template, NamedDecl)
DECL(FunctionTemplate, TemplateDecl)
DECL(ClassTemplate, TemplateDecl)
DECL(TemplateTemplateParm, TemplateDecl)
DECL(Using, NamedDecl)
+ DECL(UnresolvedUsing, NamedDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)
DECL(ObjCProtocol, ObjCContainerDecl)
DECL(ObjCInterface, ObjCContainerDecl)
+ ABSTRACT_DECL(ObjCImpl, ObjCContainerDecl)
+ DECL(ObjCCategoryImpl, ObjCImplDecl)
+ DECL(ObjCImplementation, ObjCImplDecl)
DECL(ObjCProperty, NamedDecl)
DECL(ObjCCompatibleAlias, NamedDecl)
- ABSTRACT_DECL(ObjCImpl, NamedDecl)
- DECL(ObjCCategoryImpl, ObjCImplDecl)
- DECL(ObjCImplementation, ObjCImplDecl)
DECL(LinkageSpec, Decl)
DECL(ObjCPropertyImpl, Decl)
DECL(ObjCForwardProtocol, Decl)
DECL(ObjCClass, Decl)
DECL(FileScopeAsm, Decl)
+DECL(Friend, Decl)
+DECL(FriendTemplate, Decl)
DECL(StaticAssert, Decl)
LAST_DECL(Block, Decl)
@@ -132,21 +136,20 @@ DECL_CONTEXT(TranslationUnit)
DECL_CONTEXT(Namespace)
DECL_CONTEXT(LinkageSpec)
DECL_CONTEXT(ObjCMethod)
-DECL_CONTEXT(ObjCCategoryImpl)
-DECL_CONTEXT(ObjCImplementation)
DECL_CONTEXT_BASE(Tag)
DECL_CONTEXT_BASE(Function)
DECL_CONTEXT_BASE(ObjCContainer)
LAST_DECL_CONTEXT(Block)
// Declaration ranges
-DECL_RANGE(Named, OverloadedFunction, ObjCImplementation)
-DECL_RANGE(ObjCContainer, ObjCContainer, ObjCInterface)
+DECL_RANGE(Named, OverloadedFunction, ObjCCompatibleAlias)
+DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation)
DECL_RANGE(Field, Field, ObjCAtDefsField)
DECL_RANGE(Type, Typedef, TemplateTypeParm)
DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization)
DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization)
DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm)
+DECL_RANGE(Declarator, Function, NonTypeTemplateParm)
DECL_RANGE(Function, Function, CXXConversion)
DECL_RANGE(Template, Template, TemplateTemplateParm)
DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation)
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 2fcdaa3e2959..2b12bb5c1b6d 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -43,17 +43,17 @@ public:
~ObjCListBase() {
assert(List == 0 && "Destroy should have been called before dtor");
}
-
+
void Destroy(ASTContext &Ctx);
-
+
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
-
+
protected:
void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
};
-
-
+
+
/// ObjCList - This is a simple template class used to hold various lists of
/// decls etc, which is heavily used by the ObjC front-end. This only use case
/// this supports is setting the list all at once and then reading elements out
@@ -64,30 +64,30 @@ public:
void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
}
-
+
typedef T* const * iterator;
iterator begin() const { return (iterator)List; }
iterator end() const { return (iterator)List+NumElts; }
-
+
T* operator[](unsigned Idx) const {
assert(Idx < NumElts && "Invalid access");
return (T*)List[Idx];
}
};
-
+
/// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
-/// functions leverage C syntax, Objective-C method syntax is modeled after
-/// Smalltalk (using colons to specify argument types/expressions).
+/// functions leverage C syntax, Objective-C method syntax is modeled after
+/// Smalltalk (using colons to specify argument types/expressions).
/// Here are some brief examples:
///
/// Setter/getter instance methods:
/// - (void)setMenu:(NSMenu *)menu;
-/// - (NSMenu *)menu;
-///
+/// - (NSMenu *)menu;
+///
/// Instance method that takes 2 NSView arguments:
/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
///
@@ -106,27 +106,27 @@ private:
/// instance (true) or class (false) method.
bool IsInstance : 1;
bool IsVariadic : 1;
-
+
// Synthesized declaration method for a property setter/getter
bool IsSynthesized : 1;
-
+
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
/// @required/@optional
unsigned DeclImplementation : 2;
-
+
// NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
-
+
// Type of this method.
QualType MethodDeclType;
/// ParamInfo - List of pointers to VarDecls for the formal parameters of this
/// Method.
ObjCList<ParmVarDecl> ParamInfo;
-
+
/// List of attributes for this method declaration.
- SourceLocation EndLoc; // the location of the ';' or '{'.
-
+ SourceLocation EndLoc; // the location of the ';' or '}'.
+
// The following are only used for method definitions, null otherwise.
// FIXME: space savings opportunity, consider a sub-class.
Stmt *Body;
@@ -137,7 +137,7 @@ private:
/// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
/// constructed by createImplicitParams.
ImplicitParamDecl *CmdDecl;
-
+
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T,
DeclContext *contextDecl,
@@ -150,48 +150,55 @@ private:
IsInstance(isInstance), IsVariadic(isVariadic),
IsSynthesized(isSynthesized),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
- MethodDeclType(T),
+ MethodDeclType(T),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
virtual ~ObjCMethodDecl() {}
-
+
+ /// \brief A definition will return its interface declaration.
+ /// An interface declaration will return its definition.
+ /// Otherwise it will return itself.
+ virtual ObjCMethodDecl *getNextRedeclaration();
+
public:
-
+
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
static ObjCMethodDecl *Create(ASTContext &C,
- SourceLocation beginLoc,
+ SourceLocation beginLoc,
SourceLocation endLoc, Selector SelInfo,
QualType T, DeclContext *contextDecl,
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
ImplementationControl impControl = None);
-
+
+ virtual ObjCMethodDecl *getCanonicalDecl();
+
ObjCDeclQualifier getObjCDeclQualifier() const {
return ObjCDeclQualifier(objcDeclQualifier);
}
void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
-
+
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); }
SourceLocation getLocEnd() const { return EndLoc; }
void setEndLoc(SourceLocation Loc) { EndLoc = Loc; }
- SourceRange getSourceRange() const {
- return SourceRange(getLocation(), EndLoc);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), EndLoc);
}
-
+
ObjCInterfaceDecl *getClassInterface();
const ObjCInterfaceDecl *getClassInterface() const {
return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
}
-
+
Selector getSelector() const { return getDeclName().getObjCSelector(); }
- unsigned getSynthesizedMethodSize() const;
+
QualType getResultType() const { return MethodDeclType; }
void setResultType(QualType T) { MethodDeclType = T; }
-
+
// Iterator access to formal parameters.
unsigned param_size() const { return ParamInfo.size(); }
typedef ObjCList<ParmVarDecl>::iterator param_iterator;
@@ -212,7 +219,7 @@ public:
arg_type_iterator arg_type_end() const {
return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
}
-
+
/// createImplicitParams - Used to lazily create the self and cmd
/// implict parameters. This must be called prior to using getSelfDecl()
/// or getCmdDecl(). The call is ignored if the implicit paramters
@@ -223,31 +230,34 @@ public:
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
-
+
bool isInstanceMethod() const { return IsInstance; }
void setInstanceMethod(bool isInst) { IsInstance = isInst; }
bool isVariadic() const { return IsVariadic; }
void setVariadic(bool isVar) { IsVariadic = isVar; }
-
+
bool isClassMethod() const { return !IsInstance; }
bool isSynthesized() const { return IsSynthesized; }
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
-
+
// Related to protocols declared in @protocol
- void setDeclImplementation(ImplementationControl ic) {
- DeclImplementation = ic;
+ void setDeclImplementation(ImplementationControl ic) {
+ DeclImplementation = ic;
}
- ImplementationControl getImplementationControl() const {
- return ImplementationControl(DeclImplementation);
+ ImplementationControl getImplementationControl() const {
+ return ImplementationControl(DeclImplementation);
}
- virtual Stmt *getBody() const {
- return (Stmt*) Body;
+ virtual Stmt *getBody() const {
+ return (Stmt*) Body;
}
CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; }
void setBody(Stmt *B) { Body = B; }
+ /// \brief Returns whether this specific method is a definition.
+ bool isThisDeclarationADefinition() const { return Body; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
static bool classof(const ObjCMethodDecl *D) { return true; }
@@ -263,9 +273,9 @@ public:
struct ObjCMethodList {
ObjCMethodDecl *Method;
ObjCMethodList *Next;
-
+
ObjCMethodList() {
- Method = 0;
+ Method = 0;
Next = 0;
}
ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
@@ -275,15 +285,14 @@ struct ObjCMethodList {
};
/// ObjCContainerDecl - Represents a container for method declarations.
-/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, and
-/// ObjCProtocolDecl.
-/// FIXME: Use for ObjC implementation decls.
+/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
+/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
SourceLocation AtEndLoc; // marks the end of the method container.
public:
- ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id)
: NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
@@ -291,24 +300,24 @@ public:
// Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
- prop_iterator prop_begin() const {
+ prop_iterator prop_begin() const {
return prop_iterator(decls_begin());
}
- prop_iterator prop_end() const {
+ prop_iterator prop_end() const {
return prop_iterator(decls_end());
}
-
+
// Iterator access to instance/class methods.
typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
- method_iterator meth_begin() const {
+ method_iterator meth_begin() const {
return method_iterator(decls_begin());
}
- method_iterator meth_end() const {
+ method_iterator meth_end() const {
return method_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isInstanceMethod>
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isInstanceMethod>
instmeth_iterator;
instmeth_iterator instmeth_begin() const {
return instmeth_iterator(decls_begin());
@@ -317,8 +326,8 @@ public:
return instmeth_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isClassMethod>
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isClassMethod>
classmeth_iterator;
classmeth_iterator classmeth_begin() const {
return classmeth_iterator(decls_begin());
@@ -328,23 +337,28 @@ public:
}
// Get the local instance/class method declared in this interface.
- ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
- ObjCMethodDecl *getClassMethod(Selector Sel) const;
+ ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *getInstanceMethod(Selector Sel) const {
+ return getMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *getClassMethod(Selector Sel) const {
+ return getMethod(Sel, false/*isInstance*/);
+ }
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
- ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const {
- return isInstance ? getInstanceMethod(Sel) : getClassMethod(Sel);
- }
-
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
// Marks the end of the container.
SourceLocation getAtEndLoc() const { return AtEndLoc; }
void setAtEndLoc(SourceLocation L) { AtEndLoc = L; }
-
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), getAtEndLoc());
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
- return D->getKind() >= ObjCContainerFirst &&
+ return D->getKind() >= ObjCContainerFirst &&
D->getKind() <= ObjCContainerLast;
}
static bool classof(const ObjCContainerDecl *D) { return true; }
@@ -360,11 +374,11 @@ public:
/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example:
///
/// // MostPrimitive declares no super class (not particularly useful).
-/// @interface MostPrimitive
+/// @interface MostPrimitive
/// // no instance variables or methods.
/// @end
///
-/// // NSResponder inherits from NSObject & implements NSCoding (a protocol).
+/// // NSResponder inherits from NSObject & implements NSCoding (a protocol).
/// @interface NSResponder : NSObject <NSCoding>
/// { // instance variables are represented by ObjCIvarDecl.
/// id nextResponder; // nextResponder instance variable.
@@ -383,32 +397,32 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
mutable Type *TypeForDecl;
friend class ASTContext;
-
+
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
-
+
/// Protocols referenced in interface header declaration
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
-
+
/// Instance variables in the interface.
ObjCList<ObjCIvarDecl> IVars;
-
+
/// List of categories defined for this class.
/// FIXME: Why is this a linked list??
ObjCCategoryDecl *CategoryList;
-
+
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
-
+
SourceLocation ClassLoc; // location of the class identifier.
SourceLocation SuperClassLoc; // location of the super class identifier.
SourceLocation EndLoc; // marks the '>', '}', or identifier.
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal);
-
+
virtual ~ObjCInterfaceDecl() {}
-
+
public:
/// Destroy - Call destructors and release memory.
@@ -416,16 +430,27 @@ public:
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
- IdentifierInfo *Id,
+ IdentifierInfo *Id,
SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false,
bool isInternal = false);
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
- return ReferencedProtocols;
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ return ReferencedProtocols;
}
-
+
+ ObjCImplementationDecl *getImplementation() const;
+ void setImplementation(ObjCImplementationDecl *ImplD);
+
ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
+ // Get the local instance/class method declared in a category.
+ ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
+ ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
+ ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
+ return isInstance ? getInstanceMethod(Sel)
+ : getClassMethod(Sel);
+ }
+
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
@@ -436,29 +461,34 @@ public:
ivar_iterator ivar_end() const { return IVars.end(); }
unsigned ivar_size() const { return IVars.size(); }
bool ivar_empty() const { return IVars.empty(); }
-
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
}
-
+
+ /// mergeClassExtensionProtocolList - Merge class extension's protocol list
+ /// into the protocol list for this class.
+ void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
+ ASTContext &C);
+
void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) {
IVars.set(List, Num, C);
}
bool isForwardDecl() const { return ForwardDecl; }
void setForwardDecl(bool val) { ForwardDecl = val; }
-
+
ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
-
+
ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
- void setCategoryList(ObjCCategoryDecl *category) {
+ void setCategoryList(ObjCCategoryDecl *category) {
CategoryList = category;
}
-
+
/// isSuperClassOf - Return true if this class is the specified class or is a
/// super class of the specified interface class.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
@@ -470,7 +500,7 @@ public:
}
return false;
}
-
+
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
ObjCInterfaceDecl *&ClassDeclared);
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
@@ -480,26 +510,41 @@ public:
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
- ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
- ObjCMethodDecl *lookupClassMethod(Selector Sel);
+ ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
+ return lookupMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
+ }
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
+
+ // Lookup a method in the classes implementation hierarchy.
+ ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel);
- // Location information, modeled after the Stmt API.
+ // Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
-
+
void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; }
SourceLocation getClassLoc() const { return ClassLoc; }
void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
-
+
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
/// declaration without an @interface declaration.
bool isImplicitInterfaceDecl() const { return InternalInterface; }
void setImplicitInterfaceDecl(bool val) { InternalInterface = val; }
-
+
+ /// ClassImplementsProtocol - Checks that 'lProto' protocol
+ /// has been implemented in IDecl class, its super class or categories (if
+ /// lookupCategory is true).
+ bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+ bool lookupCategory,
+ bool RHSIsQualifiedID = false);
+
// Low-level accessor
Type *getTypeForDecl() const { return TypeForDecl; }
void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
@@ -528,18 +573,19 @@ public:
enum AccessControl {
None, Private, Protected, Public, Package
};
-
+
private:
ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
- QualType T, AccessControl ac, Expr *BW)
- : FieldDecl(ObjCIvar, DC, L, Id, T, BW, /*Mutable=*/false),
+ QualType T, DeclaratorInfo *DInfo, AccessControl ac, Expr *BW)
+ : FieldDecl(ObjCIvar, DC, L, Id, T, DInfo, BW, /*Mutable=*/false),
DeclAccess(ac) {}
-
+
public:
static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
+ DeclaratorInfo *DInfo,
AccessControl ac, Expr *BW = NULL);
-
+
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
@@ -547,7 +593,7 @@ public:
AccessControl getCanonicalAccessControl() const {
return DeclAccess == None ? Protected : AccessControl(DeclAccess);
}
-
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; }
static bool classof(const ObjCIvarDecl *D) { return true; }
@@ -556,21 +602,23 @@ private:
unsigned DeclAccess : 3;
};
-
+
/// ObjCAtDefsFieldDecl - Represents a field declaration created by an
/// @defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
private:
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW)
- : FieldDecl(ObjCAtDefsField, DC, L, Id, T, BW, /*Mutable=*/false) {}
-
+ : FieldDecl(ObjCAtDefsField, DC, L, Id, T,
+ /*DInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
+ BW, /*Mutable=*/false) {}
+
public:
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id, QualType T,
Expr *BW);
-
+
virtual void Destroy(ASTContext& C);
// Implement isa/cast/dyncast/etc.
@@ -579,8 +627,8 @@ public:
};
/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
-/// declare a pure abstract type (i.e no instance variables are permitted).
-/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
+/// declare a pure abstract type (i.e no instance variables are permitted).
+/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
/// feature with nice semantics and lousy syntax:-). Here is an example:
///
/// @protocol NSDraggingInfo <refproto1, refproto2>
@@ -597,7 +645,7 @@ public:
///
/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
/// protocols are in distinct namespaces. For example, Cocoa defines both
-/// an NSObject protocol and class (which isn't allowed in Java). As a result,
+/// an NSObject protocol and class (which isn't allowed in Java). As a result,
/// protocols are referenced using angle brackets as follows:
///
/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
@@ -605,78 +653,83 @@ public:
class ObjCProtocolDecl : public ObjCContainerDecl {
/// Referenced protocols
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
-
+
bool isForwardProtoDecl; // declared with @protocol.
-
+
SourceLocation EndLoc; // marks the '>' or identifier.
-
+
ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
- : ObjCContainerDecl(ObjCProtocol, DC, L, Id),
+ : ObjCContainerDecl(ObjCProtocol, DC, L, Id),
isForwardProtoDecl(true) {
}
-
+
virtual ~ObjCProtocolDecl() {}
-
+
public:
- static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
-
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
return ReferencedProtocols;
}
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
-
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
}
-
+
ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
-
+
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
- ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
- ObjCMethodDecl *lookupClassMethod(Selector Sel);
-
+ ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
+ return lookupMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
+ }
+
bool isForwardDecl() const { return isForwardProtoDecl; }
void setForwardDecl(bool val) { isForwardProtoDecl = val; }
- // Location information, modeled after the Stmt API.
+ // Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
-
+
static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; }
static bool classof(const ObjCProtocolDecl *D) { return true; }
};
-
+
/// ObjCClassDecl - Specifies a list of forward class declarations. For example:
///
/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
///
class ObjCClassDecl : public Decl {
ObjCList<ObjCInterfaceDecl> ForwardDecls;
-
- ObjCClassDecl(DeclContext *DC, SourceLocation L,
+
+ ObjCClassDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C);
virtual ~ObjCClassDecl() {}
public:
-
+
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
-
+
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts = 0,
+ ObjCInterfaceDecl *const *Elts = 0,
unsigned nElts = 0);
-
+
typedef ObjCList<ObjCInterfaceDecl>::iterator iterator;
iterator begin() const { return ForwardDecls.begin(); }
iterator end() const { return ForwardDecls.end(); }
@@ -686,33 +739,33 @@ public:
void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) {
ForwardDecls.set(List, Num, C);
}
-
+
static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
static bool classof(const ObjCClassDecl *D) { return true; }
};
/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations.
/// For example:
-///
+///
/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
-///
+///
class ObjCForwardProtocolDecl : public Decl {
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
-
+
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
- ASTContext &C);
+ ASTContext &C);
virtual ~ObjCForwardProtocolDecl() {}
-
+
public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation L,
ObjCProtocolDecl *const *Elts = 0,
unsigned Num = 0);
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
-
+
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
@@ -731,7 +784,7 @@ public:
/// ObjCCategoryDecl - Represents a category declaration. A category allows
/// you to add methods to an existing class (without subclassing or modifying
-/// the original class interface or implementation:-). Categories don't allow
+/// the original class interface or implementation:-). Categories don't allow
/// you to add instance data. The following example adds "myMethod" to all
/// NSView's within a process:
///
@@ -743,51 +796,54 @@ public:
/// several files (a feature more naturally supported in C++).
///
/// Categories were originally inspired by dynamic languages such as Common
-/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
+/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
/// don't support this level of dynamism, which is both powerful and dangerous.
///
class ObjCCategoryDecl : public ObjCContainerDecl {
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
-
+
/// referenced protocols in this category.
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
-
+
/// Next category belonging to this class.
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
-
+
SourceLocation EndLoc; // marks the '>' or identifier.
-
+
ObjCCategoryDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, L, Id),
ClassInterface(0), NextClassCategory(0){
}
public:
-
+
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
-
+
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
-
+
+ ObjCCategoryImplDecl *getImplementation() const;
+ void setImplementation(ObjCCategoryImplDecl *ImplD);
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
}
-
- const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
return ReferencedProtocols;
}
-
+
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
-
+
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
void setNextClassCategory(ObjCCategoryDecl *Cat) {
NextClassCategory = Cat;
@@ -796,98 +852,67 @@ public:
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
}
- // Location information, modeled after the Stmt API.
+ // Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
-
+
static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
static bool classof(const ObjCCategoryDecl *D) { return true; }
};
-class ObjCImplDecl : public NamedDecl, public DeclContext {
+class ObjCImplDecl : public ObjCContainerDecl {
/// Class interface for this category implementation
ObjCInterfaceDecl *ClassInterface;
-
- SourceLocation EndLoc;
-
+
protected:
ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface)
- : NamedDecl(DK, DC, L,
- classInterface? classInterface->getDeclName()
- : DeclarationName()),
- DeclContext(DK), ClassInterface(classInterface) {}
-
+ : ObjCContainerDecl(DK, DC, L,
+ classInterface? classInterface->getIdentifier() : 0),
+ ClassInterface(classInterface) {}
+
public:
virtual ~ObjCImplDecl() {}
-
+
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
- void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; }
+ void setClassInterface(ObjCInterfaceDecl *IFace);
- void addInstanceMethod(ObjCMethodDecl *method) {
+ void addInstanceMethod(ObjCMethodDecl *method) {
// FIXME: Context should be set correctly before we get here.
method->setLexicalDeclContext(this);
- addDecl(method);
+ addDecl(method);
}
- void addClassMethod(ObjCMethodDecl *method) {
+ void addClassMethod(ObjCMethodDecl *method) {
// FIXME: Context should be set correctly before we get here.
method->setLexicalDeclContext(this);
- addDecl(method);
+ addDecl(method);
}
-
- // Get the local instance/class method declared in this interface.
- ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
- ObjCMethodDecl *getClassMethod(Selector Sel) const;
- ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const {
- return isInstance ? getInstanceMethod(Sel)
- : getClassMethod(Sel);
- }
-
+
void addPropertyImplementation(ObjCPropertyImplDecl *property);
-
+
ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
// Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
- propimpl_iterator propimpl_begin() const {
+ propimpl_iterator propimpl_begin() const {
return propimpl_iterator(decls_begin());
}
- propimpl_iterator propimpl_end() const {
+ propimpl_iterator propimpl_end() const {
return propimpl_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isInstanceMethod>
- instmeth_iterator;
- instmeth_iterator instmeth_begin() const {
- return instmeth_iterator(decls_begin());
- }
- instmeth_iterator instmeth_end() const {
- return instmeth_iterator(decls_end());
- }
-
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isClassMethod>
- classmeth_iterator;
- classmeth_iterator classmeth_begin() const {
- return classmeth_iterator(decls_begin());
- }
- classmeth_iterator classmeth_end() const {
- return classmeth_iterator(decls_end());
+ static bool classof(const Decl *D) {
+ return D->getKind() >= ObjCImplFirst && D->getKind() <= ObjCImplLast;
}
-
- // Location information, modeled after the Stmt API.
- SourceLocation getLocStart() const { return getLocation(); }
- SourceLocation getLocEnd() const { return EndLoc; }
- void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+ static bool classof(const ObjCImplDecl *D) { return true; }
};
-
-/// ObjCCategoryImplDecl - An object of this class encapsulates a category
-/// @implementation declaration. If a category class has declaration of a
-/// property, its implementation must be specified in the category's
+
+/// ObjCCategoryImplDecl - An object of this class encapsulates a category
+/// @implementation declaration. If a category class has declaration of a
+/// property, its implementation must be specified in the category's
/// @implementation declaration. Example:
/// @interface I @end
/// @interface I(CATEGORY)
@@ -909,34 +934,30 @@ public:
static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface);
-
+
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
- IdentifierInfo *getIdentifier() const {
- return Id;
+ IdentifierInfo *getIdentifier() const {
+ return Id;
}
void setIdentifier(IdentifierInfo *II) { Id = II; }
+ ObjCCategoryDecl *getCategoryClass() const;
+
/// getNameAsCString - Get the name of identifier for the class
/// interface associated with this implementation as a C string
/// (const char*).
const char *getNameAsCString() const {
return Id ? Id->getName() : "";
}
-
+
/// @brief Get the name of the class associated with this interface.
std::string getNameAsString() const {
return Id ? Id->getName() : "";
}
-
+
static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}
static bool classof(const ObjCCategoryImplDecl *D) { return true; }
- static DeclContext *castToDeclContext(const ObjCCategoryImplDecl *D) {
- return static_cast<DeclContext *>(const_cast<ObjCCategoryImplDecl*>(D));
- }
- static ObjCCategoryImplDecl *castFromDeclContext(const DeclContext *DC) {
- return static_cast<ObjCCategoryImplDecl *>(const_cast<DeclContext*>(DC));
- }
};
/// ObjCImplementationDecl - Represents a class definition - this is where
@@ -948,30 +969,30 @@ public:
/// @end
/// @endcode
///
-/// Typically, instance variables are specified in the class interface,
+/// Typically, instance variables are specified in the class interface,
/// *not* in the implementation. Nevertheless (for legacy reasons), we
/// allow instance variables to be specified in the implementation. When
/// specified, they need to be *identical* to the interface.
///
-class ObjCImplementationDecl : public ObjCImplDecl {
+class ObjCImplementationDecl : public ObjCImplDecl {
/// Implementation Class's super class.
ObjCInterfaceDecl *SuperClass;
-
- ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
+
+ ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
- : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
+ : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
SuperClass(superDecl){}
-public:
- static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+public:
+ static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl);
-
+
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
- IdentifierInfo *getIdentifier() const {
- return getClassInterface()->getIdentifier();
+ IdentifierInfo *getIdentifier() const {
+ return getClassInterface()->getIdentifier();
}
/// getNameAsCString - Get the name of identifier for the class
@@ -989,41 +1010,35 @@ public:
const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
-
+
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
-
+
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
- ivar_iterator ivar_begin() const {
- return ivar_iterator(decls_begin());
+ ivar_iterator ivar_begin() const {
+ return ivar_iterator(decls_begin());
}
- ivar_iterator ivar_end() const {
+ ivar_iterator ivar_end() const {
return ivar_iterator(decls_end());
}
- unsigned ivar_size() const {
+ unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
- bool ivar_empty() const {
+ bool ivar_empty() const {
return ivar_begin() == ivar_end();
}
-
+
static bool classof(const Decl *D) {
return D->getKind() == ObjCImplementation;
}
static bool classof(const ObjCImplementationDecl *D) { return true; }
- static DeclContext *castToDeclContext(const ObjCImplementationDecl *D) {
- return static_cast<DeclContext *>(const_cast<ObjCImplementationDecl*>(D));
- }
- static ObjCImplementationDecl *castFromDeclContext(const DeclContext *DC) {
- return static_cast<ObjCImplementationDecl *>(const_cast<DeclContext*>(DC));
- }
};
-/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
+/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
/// declared as @compatibility_alias alias class.
class ObjCCompatibleAliasDecl : public NamedDecl {
/// Class that this is an alias of.
ObjCInterfaceDecl *AliasedClass;
-
+
ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl* aliasedClass)
: NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
@@ -1035,12 +1050,12 @@ public:
const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
-
+
static bool classof(const Decl *D) {
return D->getKind() == ObjCCompatibleAlias;
}
static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
-
+
};
/// ObjCPropertyDecl - Represents one property declaration in an interface.
@@ -1050,13 +1065,13 @@ public:
class ObjCPropertyDecl : public NamedDecl {
public:
enum PropertyAttributeKind {
- OBJC_PR_noattr = 0x00,
- OBJC_PR_readonly = 0x01,
+ OBJC_PR_noattr = 0x00,
+ OBJC_PR_readonly = 0x01,
OBJC_PR_getter = 0x02,
- OBJC_PR_assign = 0x04,
- OBJC_PR_readwrite = 0x08,
+ OBJC_PR_assign = 0x04,
+ OBJC_PR_readwrite = 0x08,
OBJC_PR_retain = 0x10,
- OBJC_PR_copy = 0x20,
+ OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
OBJC_PR_setter = 0x80
};
@@ -1066,27 +1081,27 @@ public:
private:
QualType DeclType;
unsigned PropertyAttributes : 8;
-
+
// @required/@optional
unsigned PropertyImplementation : 2;
-
+
Selector GetterName; // getter name of NULL if no getter
Selector SetterName; // setter name of NULL if no setter
-
+
ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
- ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T)
: NamedDecl(ObjCProperty, DC, L, Id), DeclType(T),
PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
- GetterName(Selector()),
+ GetterName(Selector()),
SetterName(Selector()),
GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
public:
- static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
IdentifierInfo *Id, QualType T,
PropertyControl propControl = None);
QualType getType() const { return DeclType; }
@@ -1095,14 +1110,14 @@ public:
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
- void setPropertyAttributes(PropertyAttributeKind PRVal) {
+ void setPropertyAttributes(PropertyAttributeKind PRVal) {
PropertyAttributes |= PRVal;
}
void makeitReadWriteAttribute(void) {
PropertyAttributes &= ~OBJC_PR_readonly;
PropertyAttributes |= OBJC_PR_readwrite;
- }
+ }
// Helper methods for accessing attributes.
@@ -1124,38 +1139,38 @@ public:
Selector getGetterName() const { return GetterName; }
void setGetterName(Selector Sel) { GetterName = Sel; }
-
+
Selector getSetterName() const { return SetterName; }
void setSetterName(Selector Sel) { SetterName = Sel; }
-
+
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
-
+
// Related to @optional/@required declared in @protocol
void setPropertyImplementation(PropertyControl pc) {
PropertyImplementation = pc;
}
PropertyControl getPropertyImplementation() const {
return PropertyControl(PropertyImplementation);
- }
-
+ }
+
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
PropertyIvarDecl = Ivar;
}
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
-
+
static bool classof(const Decl *D) {
return D->getKind() == ObjCProperty;
}
static bool classof(const ObjCPropertyDecl *D) { return true; }
};
-/// ObjCPropertyImplDecl - Represents implementation declaration of a property
+/// ObjCPropertyImplDecl - Represents implementation declaration of a property
/// in a class or category implementation block. For example:
/// @synthesize prop1 = ivar1;
///
@@ -1174,21 +1189,24 @@ private:
ObjCIvarDecl *PropertyIvarDecl;
ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
- ObjCPropertyDecl *property,
- Kind PK,
+ ObjCPropertyDecl *property,
+ Kind PK,
ObjCIvarDecl *ivarDecl)
- : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
+ : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
assert (PK == Dynamic || PropertyIvarDecl);
}
-
+
public:
static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation atLoc, SourceLocation L,
- ObjCPropertyDecl *property,
- Kind PK,
+ SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
ObjCIvarDecl *ivarDecl);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getLocation());
+ }
SourceLocation getLocStart() const { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
@@ -1200,7 +1218,7 @@ public:
Kind getPropertyImplementation() const {
return PropertyIvarDecl ? Synthesize : Dynamic;
}
-
+
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
@@ -1209,7 +1227,7 @@ public:
static bool classof(const Decl *D) {
return D->getKind() == ObjCPropertyImpl;
}
- static bool classof(const ObjCPropertyImplDecl *D) { return true; }
+ static bool classof(const ObjCPropertyImplDecl *D) { return true; }
};
} // end namespace clang
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 5d0fe158e054..8d44676124fb 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -49,38 +49,38 @@ class TemplateParameterList {
unsigned NumParams;
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- Decl **Params, unsigned NumParams,
+ NamedDecl **Params, unsigned NumParams,
SourceLocation RAngleLoc);
public:
- static TemplateParameterList *Create(ASTContext &C,
+ static TemplateParameterList *Create(ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- Decl **Params,
+ NamedDecl **Params,
unsigned NumParams,
SourceLocation RAngleLoc);
/// iterator - Iterates through the template parameters in this list.
- typedef Decl** iterator;
+ typedef NamedDecl** iterator;
/// const_iterator - Iterates through the template parameters in this list.
- typedef Decl* const* const_iterator;
+ typedef NamedDecl* const* const_iterator;
- iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
+ iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
const_iterator begin() const {
- return reinterpret_cast<Decl * const *>(this + 1);
+ return reinterpret_cast<NamedDecl * const *>(this + 1);
}
iterator end() { return begin() + NumParams; }
const_iterator end() const { return begin() + NumParams; }
unsigned size() const { return NumParams; }
- Decl* getParam(unsigned Idx) {
+ NamedDecl* getParam(unsigned Idx) {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
}
- const Decl* getParam(unsigned Idx) const {
+ const NamedDecl* getParam(unsigned Idx) const {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
}
@@ -115,10 +115,10 @@ class TemplateArgument {
bool CopyArgs;
} Args;
};
-
+
/// \brief Location of the beginning of this template argument.
SourceLocation StartLoc;
-
+
public:
/// \brief The type of template argument we're storing.
enum ArgKind {
@@ -133,21 +133,21 @@ public:
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression = 4,
-
+
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack = 5
} Kind;
-
+
/// \brief Construct an empty, invalid template argument.
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
-
+
/// \brief Construct a template type argument.
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
StartLoc = Loc;
}
-
+
/// \brief Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
@@ -156,7 +156,7 @@ public:
TypeOrValue = reinterpret_cast<uintptr_t>(D);
StartLoc = Loc;
}
-
+
/// \brief Construct an integral constant template argument.
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
QualType Type)
@@ -165,14 +165,14 @@ public:
Integer.Type = Type.getAsOpaquePtr();
StartLoc = Loc;
}
-
- /// \brief Construct a template argument that is an expression.
+
+ /// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
/// lists used for dependent types and for expression; it will not
/// occur in a non-dependent, canonical template argument list.
TemplateArgument(Expr *E);
-
+
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
if (Kind == Integral) {
@@ -188,27 +188,27 @@ public:
TypeOrValue = Other.TypeOrValue;
StartLoc = Other.StartLoc;
}
-
+
TemplateArgument& operator=(const TemplateArgument& Other) {
// FIXME: Does not provide the strong guarantee for exception
// safety.
using llvm::APSInt;
-
+
// FIXME: Handle Packs
assert(Kind != Pack && "FIXME: Handle packs");
assert(Other.Kind != Pack && "FIXME: Handle packs");
-
+
if (Kind == Other.Kind && Kind == Integral) {
// Copy integral values.
*this->getAsIntegral() = *Other.getAsIntegral();
- Integer.Type = Other.Integer.Type;
+ Integer.Type = Other.Integer.Type;
} else {
// Destroy the current integral value, if that's what we're holding.
if (Kind == Integral)
getAsIntegral()->~APSInt();
-
+
Kind = Other.Kind;
-
+
if (Other.Kind == Integral) {
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
@@ -216,133 +216,131 @@ public:
TypeOrValue = Other.TypeOrValue;
}
StartLoc = Other.StartLoc;
-
+
return *this;
}
-
+
~TemplateArgument() {
using llvm::APSInt;
-
+
if (Kind == Integral)
getAsIntegral()->~APSInt();
else if (Kind == Pack && Args.CopyArgs)
delete[] Args.Args;
}
-
+
/// \brief Return the kind of stored template argument.
ArgKind getKind() const { return Kind; }
-
+
/// \brief Determine whether this template argument has no value.
bool isNull() const { return Kind == Null; }
-
+
/// \brief Retrieve the template argument as a type.
QualType getAsType() const {
if (Kind != Type)
return QualType();
-
- return QualType::getFromOpaquePtr(
- reinterpret_cast<void*>(TypeOrValue));
+
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
}
-
+
/// \brief Retrieve the template argument as a declaration.
Decl *getAsDecl() const {
if (Kind != Declaration)
return 0;
return reinterpret_cast<Decl *>(TypeOrValue);
}
-
+
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
return 0;
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
}
-
+
const llvm::APSInt *getAsIntegral() const {
return const_cast<TemplateArgument*>(this)->getAsIntegral();
}
-
+
/// \brief Retrieve the type of the integral value.
QualType getIntegralType() const {
if (Kind != Integral)
return QualType();
-
+
return QualType::getFromOpaquePtr(Integer.Type);
}
-
+
void setIntegralType(QualType T) {
- assert(Kind == Integral &&
+ assert(Kind == Integral &&
"Cannot set the integral type of a non-integral template argument");
Integer.Type = T.getAsOpaquePtr();
};
-
+
/// \brief Retrieve the template argument as an expression.
Expr *getAsExpr() const {
if (Kind != Expression)
return 0;
-
+
return reinterpret_cast<Expr *>(TypeOrValue);
}
-
+
/// \brief Iterator that traverses the elements of a template argument pack.
typedef const TemplateArgument * pack_iterator;
-
- /// \brief Iterator referencing the first argument of a template argument
+
+ /// \brief Iterator referencing the first argument of a template argument
/// pack.
pack_iterator pack_begin() const {
assert(Kind == Pack);
return Args.Args;
}
-
+
/// \brief Iterator referencing one past the last argument of a template
/// argument pack.
pack_iterator pack_end() const {
assert(Kind == Pack);
return Args.Args + Args.NumArgs;
}
-
+
/// \brief The number of template arguments in the given template argument
/// pack.
unsigned pack_size() const {
assert(Kind == Pack);
return Args.NumArgs;
}
-
+
/// \brief Retrieve the location where the template argument starts.
SourceLocation getLocation() const { return StartLoc; }
-
+
/// \brief Construct a template argument pack.
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
-
+
/// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const {
ID.AddInteger(Kind);
switch (Kind) {
case Null:
break;
-
+
case Type:
getAsType().Profile(ID);
break;
-
+
case Declaration:
- ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
+ ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
break;
-
+
case Integral:
getAsIntegral()->Profile(ID);
getIntegralType().Profile(ID);
break;
-
+
case Expression:
- // FIXME: We need a canonical representation of expressions.
- ID.AddPointer(getAsExpr());
+ getAsExpr()->Profile(ID, Context, true);
break;
-
+
case Pack:
ID.AddInteger(Args.NumArgs);
for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I].Profile(ID);
+ Args.Args[I].Profile(ID, Context);
}
}
};
@@ -352,47 +350,47 @@ class TemplateArgumentListBuilder {
TemplateArgument *StructuredArgs;
unsigned MaxStructuredArgs;
unsigned NumStructuredArgs;
-
+
TemplateArgument *FlatArgs;
unsigned MaxFlatArgs;
unsigned NumFlatArgs;
-
+
bool AddingToPack;
unsigned PackBeginIndex;
-
+
public:
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
unsigned NumTemplateArgs)
- : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
- NumStructuredArgs(0), FlatArgs(0),
+ : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
+ NumStructuredArgs(0), FlatArgs(0),
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
AddingToPack(false), PackBeginIndex(0) { }
-
+
void Append(const TemplateArgument& Arg);
void BeginPack();
void EndPack();
-
+
void ReleaseArgs();
-
- unsigned flatSize() const {
+
+ unsigned flatSize() const {
return NumFlatArgs;
}
const TemplateArgument *getFlatArguments() const {
return FlatArgs;
}
-
+
unsigned structuredSize() const {
// If we don't have any structured args, just reuse the flat size.
if (!StructuredArgs)
return flatSize();
-
+
return NumStructuredArgs;
}
const TemplateArgument *getStructuredArguments() const {
// If we don't have any structured args, just reuse the flat args.
if (!StructuredArgs)
return getFlatArguments();
-
+
return StructuredArgs;
}
};
@@ -408,44 +406,47 @@ class TemplateArgumentList {
/// The integer value will be non-zero to indicate that this
/// template argument list does not own the pointer.
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
-
+
/// \brief The number of template arguments in this template
/// argument list.
unsigned NumFlatArguments;
-
+
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
unsigned NumStructuredArguments;
-
+
public:
TemplateArgumentList(ASTContext &Context,
TemplateArgumentListBuilder &Builder,
bool TakeArgs);
+
+ /// \brief Produces a shallow copy of the given template argument list
+ TemplateArgumentList(const TemplateArgumentList &Other);
~TemplateArgumentList();
-
+
/// \brief Retrieve the template argument at a given index.
- const TemplateArgument &get(unsigned Idx) const {
+ const TemplateArgument &get(unsigned Idx) const {
assert(Idx < NumFlatArguments && "Invalid template argument index");
return getFlatArgumentList()[Idx];
}
-
+
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
-
+
/// \brief Retrieve the number of template arguments in this
/// template argument list.
unsigned size() const { return NumFlatArguments; }
-
+
/// \brief Retrieve the number of template arguments in the
/// flattened template argument list.
unsigned flat_size() const { return NumFlatArguments; }
-
+
/// \brief Retrieve the flattened template argument list.
- const TemplateArgument *getFlatArgumentList() const {
+ const TemplateArgument *getFlatArgumentList() const {
return FlatArguments.getPointer();
}
};
-
+
//===----------------------------------------------------------------------===//
// Kinds of Templates
//===----------------------------------------------------------------------===//
@@ -459,15 +460,13 @@ protected:
// This is probably never used.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0)
- { }
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { }
// Construct a template decl with the given name and parameters.
// Used when there is not templated element (tt-params, alias?).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params)
- { }
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) { }
// Construct a template decl with name, parameters, and templated element.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
@@ -499,82 +498,161 @@ protected:
NamedDecl *TemplatedDecl;
TemplateParameterList* TemplateParams;
};
-
-/// \brief Provides information about a function template specialization,
+
+/// \brief Provides information about a function template specialization,
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
public:
- /// \brief The function template specialization that this structure
+ /// \brief The function template specialization that this structure
/// describes.
FunctionDecl *Function;
-
- /// \brief The function template from which this function template
+
+ /// \brief The function template from which this function template
/// specialization was generated.
///
- /// The bit will be 0 for an implicit instantiation, 1 for an explicit
- /// specialization.
- llvm::PointerIntPair<FunctionTemplateDecl *, 1> Template;
-
+ /// The two bits are contain the top 4 values of TemplateSpecializationKind.
+ llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
+
/// \brief The template arguments used to produce the function template
/// specialization from the function template.
const TemplateArgumentList *TemplateArguments;
+
+ /// \brief The point at which this function template specialization was
+ /// first instantiated.
+ SourceLocation PointOfInstantiation;
/// \brief Retrieve the template from which this function was specialized.
FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
+
+ /// \brief Determine what kind of template specialization this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const {
+ return (TemplateSpecializationKind)(Template.getInt() + 1);
+ }
+
+ /// \brief Set the template specialization kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode TSK_Undeclared for a function template specialization");
+ Template.setInt(TSK - 1);
+ }
+
+ /// \brief Retrieve the first point of instantiation of this function
+ /// template specialization.
+ ///
+ /// The point of instantiation may be an invalid source location if this
+ /// function has yet to be instantiated.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
- /// \brief Determine whether this is an explicit specialization.
- bool isExplicitSpecialization() const { return Template.getInt(); }
-
- /// \brief Set whether this is an explicit specialization or an implicit
- /// instantiation.
- void setExplicitSpecialization(bool ES) {
- Template.setInt(ES);
+ /// \brief Set the (first) point of instantiation of this function template
+ /// specialization.
+ void setPointOfInstantiation(SourceLocation POI) {
+ PointOfInstantiation = POI;
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, TemplateArguments->getFlatArgumentList(),
- TemplateArguments->flat_size());
+ Profile(ID, TemplateArguments->getFlatArgumentList(),
+ TemplateArguments->flat_size(),
+ Function->getASTContext());
}
-
- static void
- Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, ASTContext &Context) {
ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
- TemplateArgs[Arg].Profile(ID);
- }
+ TemplateArgs[Arg].Profile(ID, Context);
+ }
+};
+
+/// \brief Provides information a specialization of a member of a class
+/// template, which may be a member function, static data member, or
+/// member class.
+class MemberSpecializationInfo {
+ // The member declaration from which this member was instantiated, and the
+ // manner in which the instantiation occurred (in the lower two bits).
+ llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
+
+ // The point at which this member was first instantiated.
+ SourceLocation PointOfInstantiation;
+
+public:
+ explicit
+ MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK)
+ : MemberAndTSK(IF, TSK - 1), PointOfInstantiation() {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode undeclared template specializations for members");
+ }
+
+ /// \brief Retrieve the member declaration from which this member was
+ /// instantiated.
+ NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); }
+
+ /// \brief Determine what kind of template specialization this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const {
+ return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1);
+ }
+
+ /// \brief Set the template specialization kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode undeclared template specializations for members");
+ MemberAndTSK.setInt(TSK - 1);
+ }
+
+ /// \brief Retrieve the first point of instantiation of this member.
+ /// If the point of instantiation is an invalid location, then this member
+ /// has not yet been instantiated.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ /// \brief Set the first point of instantiation.
+ void setPointOfInstantiation(SourceLocation POI) {
+ PointOfInstantiation = POI;
+ }
};
/// Declaration of a template function.
-class FunctionTemplateDecl : public TemplateDecl {
+class FunctionTemplateDecl : public TemplateDecl {
protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common {
+ Common() : InstantiatedFromMember(0, false) { }
+
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+
+ /// \brief The member function template from which this was most
+ /// directly instantiated (or null).
+ ///
+ /// The boolean value indicates whether this member function template
+ /// was explicitly specialized.
+ llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
};
-
+
/// \brief A pointer to the previous declaration (if this is a redeclaration)
/// or to the data that is common to all declarations of this function
/// template.
llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
-
- /// \brief Retrieves the "common" pointer shared by all
+
+ /// \brief Retrieves the "common" pointer shared by all
/// (re-)declarations of the same function template. Calling this routine
/// may implicitly allocate memory for the common pointer.
Common *getCommonPtr();
-
+
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
CommonOrPrev((Common*)0) { }
-
+
public:
void Destroy(ASTContext &C);
-
+
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
@@ -585,7 +663,7 @@ public:
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
-
+
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
@@ -597,12 +675,71 @@ public:
FunctionTemplateDecl *getPreviousDeclaration() {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
-
+
/// \brief Set the previous declaration of this function template.
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
if (Prev)
CommonOrPrev = Prev;
}
+
+ virtual FunctionTemplateDecl *getCanonicalDecl();
+
+ /// \brief Retrieve the member function template that this function template
+ /// was instantiated from.
+ ///
+ /// This routine will return non-NULL for member function templates of
+ /// class templates. For example, given:
+ ///
+ /// \code
+ /// template <typename T>
+ /// struct X {
+ /// template <typename U> void f();
+ /// };
+ /// \endcode
+ ///
+ /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
+ /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
+ /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
+ /// ClassTemplateDecl).
+ ///
+ /// \returns NULL if this is not an instantiation of a member function
+ /// template.
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return getCommonPtr()->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
+ getCommonPtr()->InstantiatedFromMember.setPointer(FTD);
+ }
+
+ /// \brief Determines whether this template was a specialization of a
+ /// member template.
+ ///
+ /// In the following example, the function template \c X<int>::f is a
+ /// member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> void f(T, U);
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// void X<int>::f(int, T);
+ /// \endcode
+ bool isMemberSpecialization() {
+ return getCommonPtr()->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ getCommonPtr()->InstantiatedFromMember.setInt(true);
+ }
/// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
@@ -629,8 +766,7 @@ public:
/// the occurrence within the parameter list.
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
-class TemplateParmPosition
-{
+class TemplateParmPosition {
protected:
// FIXME: This should probably never be called, but it's here as
TemplateParmPosition()
@@ -652,7 +788,7 @@ public:
/// Get the position of the template parameter within its parameter list.
unsigned getPosition() const { return Position; }
-
+
/// Get the index of the template parameter within its parameter list.
unsigned getIndex() const { return Position; }
};
@@ -681,10 +817,10 @@ class TemplateTypeParmDecl : public TypeDecl {
/// \brief The default template argument, if any.
QualType DefaultArgument;
- TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
- InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
+ InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
TypeForDecl = Type.getTypePtr();
}
@@ -745,21 +881,20 @@ class NonTypeTemplateParmDecl
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
- SourceLocation TSSL = SourceLocation())
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL),
- TemplateParmPosition(D, P), DefaultArgument(0)
+ DeclaratorInfo *DInfo)
+ : VarDecl(NonTypeTemplateParm, DC, L, Id, T, DInfo, VarDecl::None),
+ TemplateParmPosition(D, P), DefaultArgument(0)
{ }
public:
static NonTypeTemplateParmDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id, QualType T,
- SourceLocation TypeSpecStartLoc = SourceLocation());
+ unsigned P, IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
-
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
@@ -811,7 +946,7 @@ public:
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
-
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
@@ -834,24 +969,6 @@ public:
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
};
-// \brief Describes the kind of template specialization that a
-// particular template specialization declaration represents.
-enum TemplateSpecializationKind {
- /// This template specialization was formed from a template-id but
- /// has not yet been declared, defined, or instantiated.
- TSK_Undeclared = 0,
- /// This template specialization was declared or defined by an
- /// explicit specialization (C++ [temp.expl.spec]) or partial
- /// specialization (C++ [temp.class.spec]).
- TSK_ExplicitSpecialization,
- /// This template specialization was implicitly instantiated from a
- /// template. (C++ [temp.inst]).
- TSK_ImplicitInstantiation,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation request (C++ [temp.explicit]).
- TSK_ExplicitInstantiation
-};
-
/// \brief Represents a class template specialization, which refers to
/// a class template with a given set of template arguments.
///
@@ -861,28 +978,47 @@ enum TemplateSpecializationKind {
///
/// \code
/// template<typename T> class array;
-///
-/// template<>
+///
+/// template<>
/// class array<bool> { }; // class template specialization array<bool>
/// \endcode
-class ClassTemplateSpecializationDecl
+class ClassTemplateSpecializationDecl
: public CXXRecordDecl, public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a class template
+ /// specialization that was instantiated from a class template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The class template partial specialization from which this
+ /// class template specialization was instantiated.
+ ClassTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the class template
+ /// partial specialization itself.
+ TemplateArgumentList *TemplateArgs;
+ };
+
/// \brief The template that this specialization specializes
- ClassTemplateDecl *SpecializedTemplate;
+ llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
+ SpecializedTemplate;
/// \brief The template arguments used to describe this specialization.
TemplateArgumentList TemplateArgs;
+ /// \brief The point where this template was instantiated (if any)
+ SourceLocation PointOfInstantiation;
+
/// \brief The kind of specialization this declaration refers to.
/// Really a value of type TemplateSpecializationKind.
- unsigned SpecializationKind : 2;
+ unsigned SpecializationKind : 3;
protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
DeclContext *DC, SourceLocation L,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder);
-
+ TemplateArgumentListBuilder &Builder,
+ ClassTemplateSpecializationDecl *PrevDecl);
+
public:
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
@@ -890,12 +1026,18 @@ public:
TemplateArgumentListBuilder &Builder,
ClassTemplateSpecializationDecl *PrevDecl);
+ virtual void Destroy(ASTContext& C);
+
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
/// \brief Retrieve the template that this specialization specializes.
- ClassTemplateDecl *getSpecializedTemplate() const {
- return SpecializedTemplate;
- }
+ ClassTemplateDecl *getSpecializedTemplate() const;
- const TemplateArgumentList &getTemplateArgs() const {
+ /// \brief Retrieve the template arguments of the class template
+ /// specialization.
+ const TemplateArgumentList &getTemplateArgs() const {
return TemplateArgs;
}
@@ -909,6 +1051,67 @@ public:
SpecializationKind = TSK;
}
+ /// \brief Get the point of instantiation (if any), or null if none.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ void setPointOfInstantiation(SourceLocation Loc) {
+ assert(Loc.isValid() && "point of instantiation must be valid!");
+ PointOfInstantiation = Loc;
+ }
+
+ /// \brief If this class template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// class template or class template partial specialization from which it
+ /// was instantiated.
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ return (ClassTemplateDecl*)0;
+
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization;
+
+ return const_cast<ClassTemplateDecl*>(
+ SpecializedTemplate.get<ClassTemplateDecl*>());
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate members of the class template or class template partial
+ /// specialization from which this class template specialization was
+ /// instantiated.
+ ///
+ /// \returns For a class template specialization instantiated from the primary
+ /// template, this function will return the same template arguments as
+ /// getTemplateArgs(). For a class template specialization instantiated from
+ /// a class template partial specialization, this function will return the
+ /// deduced template arguments for the class template partial specialization
+ /// itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this class template specialization is actually an
+ /// instantiation of the given class template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
+ TemplateArgumentList *TemplateArgs) {
+ SpecializedPartialSpecialization *PS
+ = new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
/// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(QualType T) {
@@ -916,18 +1119,19 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size());
+ Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(),
+ getASTContext());
}
- static void
- Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, ASTContext &Context) {
ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
- TemplateArgs[Arg].Profile(ID);
+ TemplateArgs[Arg].Profile(ID, Context);
}
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() == ClassTemplateSpecialization ||
D->getKind() == ClassTemplatePartialSpecialization;
}
@@ -941,19 +1145,21 @@ public:
}
};
-class ClassTemplatePartialSpecializationDecl
- : public ClassTemplateSpecializationDecl
-{
- /// \brief The list of template parameters
+class ClassTemplatePartialSpecializationDecl
+ : public ClassTemplateSpecializationDecl {
+ /// \brief The list of template parameters
TemplateParameterList* TemplateParams;
ClassTemplatePartialSpecializationDecl(ASTContext &Context,
DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder)
- : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization,
- DC, L, SpecializedTemplate, Builder),
+ TemplateArgumentListBuilder &Builder,
+ ClassTemplatePartialSpecializationDecl *PrevDecl)
+ : ClassTemplateSpecializationDecl(Context,
+ ClassTemplatePartialSpecialization,
+ DC, L, SpecializedTemplate, Builder,
+ PrevDecl),
TemplateParams(Params) { }
public:
@@ -971,7 +1177,7 @@ public:
// FIXME: Add Profile support!
- static bool classof(const Decl *D) {
+ static bool classof(const Decl *D) {
return D->getKind() == ClassTemplatePartialSpecialization;
}
@@ -986,29 +1192,41 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common {
+ Common() : InstantiatedFromMember(0, 0) {}
+
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
/// \brief The class template partial specializations for this class
/// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
PartialSpecializations;
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
+
+ /// \brief The templated member class from which this was most
+ /// directly instantiated (or null).
+ ///
+ /// The boolean value indicates whether this member class template
+ /// was explicitly specialized.
+ llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember;
};
+ // FIXME: Combine PreviousDeclaration with CommonPtr, as in
+ // FunctionTemplateDecl.
+
/// \brief Previous declaration of this class template.
ClassTemplateDecl *PreviousDeclaration;
/// \brief Pointer to the data that is common to all of the
/// declarations of this class template.
- ///
+ ///
/// The first declaration of a class template (e.g., the declaration
/// with no "previous declaration") owns this pointer.
Common *CommonPtr;
-
+
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl,
ClassTemplateDecl *PrevDecl, Common *CommonPtr)
@@ -1028,6 +1246,8 @@ public:
return PreviousDeclaration;
}
+ virtual ClassTemplateDecl *getCanonicalDecl();
+
/// Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -1048,6 +1268,16 @@ public:
return CommonPtr->PartialSpecializations;
}
+ /// \brief Find a class template partial specialization with the given
+ /// type T.
+ ///
+ /// \brief A dependent type that names a specialization of this class
+ /// template.
+ ///
+ /// \returns the class template partial specialization that exactly matches
+ /// the type \p T, or NULL if no such partial specialization exists.
+ ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
+
/// \brief Retrieve the type of the injected-class-name for this
/// class template.
///
@@ -1064,6 +1294,61 @@ public:
/// \endcode
QualType getInjectedClassNameType(ASTContext &Context);
+ /// \brief Retrieve the member class template that this class template was
+ /// derived from.
+ ///
+ /// This routine will return non-NULL for templated member classes of
+ /// class templates. For example, given:
+ ///
+ /// \code
+ /// template <typename T>
+ /// struct X {
+ /// template <typename U> struct A {};
+ /// };
+ /// \endcode
+ ///
+ /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
+ /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
+ /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
+ ///
+ /// \returns null if this is not an instantiation of a member class template.
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return CommonPtr->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
+ assert(!CommonPtr->InstantiatedFromMember.getPointer());
+ CommonPtr->InstantiatedFromMember.setPointer(CTD);
+ }
+
+ /// \brief Determines whether this template was a specialization of a
+ /// member template.
+ ///
+ /// In the following example, the member template \c X<int>::Inner is a
+ /// member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> struct Inner;
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// struct X<int>::Inner { /* ... */ };
+ /// \endcode
+ bool isMemberSpecialization() {
+ return CommonPtr->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ assert(CommonPtr->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ CommonPtr->InstantiatedFromMember.setInt(true);
+ }
+
// Implement isa/cast/dyncast support
static bool classof(const Decl *D)
{ return D->getKind() == ClassTemplate; }
@@ -1073,8 +1358,87 @@ public:
virtual void Destroy(ASTContext& C);
};
+/// Declaration of a friend template. For example:
+///
+/// template <typename T> class A {
+/// friend class MyVector<T>; // not a friend template
+/// template <typename U> friend class B; // friend template
+/// template <typename U> friend class Foo<T>::Nested; // friend template
+class FriendTemplateDecl : public Decl {
+public:
+ typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
+
+private:
+ // The number of template parameters; always non-zero.
+ unsigned NumParams;
+
+ // The parameter list.
+ TemplateParameterList **Params;
+
+ // The declaration that's a friend of this class.
+ FriendUnion Friend;
+
+ // Location of the 'friend' specifier.
+ SourceLocation FriendLoc;
+
+
+ FriendTemplateDecl(DeclContext *DC, SourceLocation Loc,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FriendLoc)
+ : Decl(Decl::FriendTemplate, DC, Loc),
+ NumParams(NParams),
+ Params(Params),
+ Friend(Friend),
+ FriendLoc(FriendLoc)
+ {}
+
+public:
+ static FriendTemplateDecl *Create(ASTContext &Context,
+ DeclContext *DC, SourceLocation Loc,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FriendLoc);
+
+ /// If this friend declaration names a templated type (or
+ /// a dependent member type of a templated type), return that
+ /// type; otherwise return null.
+ Type *getFriendType() const {
+ return Friend.dyn_cast<Type*>();
+ }
+
+ /// If this friend declaration names a templated function (or
+ /// a member function of a templated type), return that type;
+ /// otherwise return null.
+ NamedDecl *getFriendDecl() const {
+ return Friend.dyn_cast<NamedDecl*>();
+ }
+
+ /// Retrieves the location of the 'friend' keyword.
+ SourceLocation getFriendLoc() const {
+ return FriendLoc;
+ }
+
+ TemplateParameterList *getTemplateParameterList(unsigned i) const {
+ assert(i <= NumParams);
+ return Params[i];
+ }
+
+ unsigned getNumTemplateParameters() const {
+ return NumParams;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::FriendTemplate;
+ }
+ static bool classof(const FriendTemplateDecl *D) { return true; }
+};
+
/// Implementation of inline functions that require the template declarations
-inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
+inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
: Function(FTD) { }
} /* end of namespace clang */
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index db140999b045..ed4ac6b5d4e7 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -15,6 +15,8 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/Basic/PartialDiagnostic.h"
namespace llvm {
template <typename T> struct DenseMapInfo;
@@ -100,7 +102,7 @@ private:
/// CXXSpecialName, returns a pointer to it. Otherwise, returns
/// a NULL pointer.
CXXSpecialName *getAsCXXSpecialName() const {
- if (getNameKind() >= CXXConstructorName &&
+ if (getNameKind() >= CXXConstructorName &&
getNameKind() <= CXXConversionFunctionName)
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
return 0;
@@ -115,16 +117,16 @@ private:
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
- DeclarationName(CXXSpecialName *Name)
- : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ DeclarationName(CXXSpecialName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
Ptr |= StoredDeclarationNameExtra;
}
// Construct a declaration name from the name of a C++ overloaded
// operator.
- DeclarationName(CXXOperatorIdName *Name)
- : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ DeclarationName(CXXOperatorIdName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
@@ -144,8 +146,8 @@ public:
DeclarationName() : Ptr(0) { }
// Construct a declaration name from an IdentifierInfo *.
- DeclarationName(const IdentifierInfo *II)
- : Ptr(reinterpret_cast<uintptr_t>(II)) {
+ DeclarationName(const IdentifierInfo *II)
+ : Ptr(reinterpret_cast<uintptr_t>(II)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
}
@@ -157,8 +159,8 @@ public:
// operator bool() - Evaluates true when this declaration name is
// non-empty.
- operator bool() const {
- return ((Ptr & PtrMask) != 0) ||
+ operator bool() const {
+ return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
@@ -170,10 +172,10 @@ public:
bool isObjCOneArgSelector() const {
return getStoredNameKind() == StoredObjCOneArgSelector;
}
-
+
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
-
+
/// getName - Retrieve the human-readable string for this name.
std::string getAsString() const;
@@ -181,7 +183,7 @@ public:
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
- IdentifierInfo *getAsIdentifierInfo() const {
+ IdentifierInfo *getAsIdentifierInfo() const {
if (isIdentifier())
return reinterpret_cast<IdentifierInfo *>(Ptr);
return 0;
@@ -195,12 +197,18 @@ public:
/// an opaque pointer.
void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
+ static DeclarationName getFromOpaquePtr(void *P) {
+ DeclarationName N;
+ N.Ptr = reinterpret_cast<uintptr_t> (P);
+ return N;
+ }
+
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
return N;
}
-
+
/// getCXXNameType - If this name is one of the C++ names (of a
/// constructor, destructor, or conversion function), return the
/// type associated with that name.
@@ -290,32 +298,32 @@ public:
/// getCXXConstructorName - Returns the name of a C++ constructor
/// for the given Type.
- DeclarationName getCXXConstructorName(QualType Ty) {
+ DeclarationName getCXXConstructorName(CanQualType Ty) {
return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
}
/// getCXXDestructorName - Returns the name of a C++ destructor
/// for the given Type.
- DeclarationName getCXXDestructorName(QualType Ty) {
+ DeclarationName getCXXDestructorName(CanQualType Ty) {
return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
}
/// getCXXConversionFunctionName - Returns the name of a C++
/// conversion function for the given Type.
- DeclarationName getCXXConversionFunctionName(QualType Ty) {
+ DeclarationName getCXXConversionFunctionName(CanQualType Ty) {
return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
}
/// getCXXSpecialName - Returns a declaration name for special kind
/// of C++ name, e.g., for a constructor, destructor, or conversion
/// function.
- DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
- QualType Ty);
+ DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
+ CanQualType Ty);
/// getCXXOperatorName - Get the name of the overloadable C++
/// operator corresponding to Op.
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
-};
+};
/// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<.
@@ -325,7 +333,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
Diagnostic::ak_declarationname);
return DB;
}
-
+
+/// Insertion operator for partial diagnostics. This allows binding
+/// DeclarationName's into a partial diagnostic with <<.
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ DeclarationName N) {
+ PD.AddTaggedVal(N.getAsOpaqueInteger(),
+ Diagnostic::ak_declarationname);
+ return PD;
+}
} // end namespace clang
@@ -344,7 +360,7 @@ struct DenseMapInfo<clang::DeclarationName> {
static unsigned getHashValue(clang::DeclarationName);
- static inline bool
+ static inline bool
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
return LHS == RHS;
}
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 6a1046e6d03f..d5dff5065d49 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <vector>
namespace clang {
@@ -42,20 +43,20 @@ class Expr : public Stmt {
QualType TR;
protected:
- /// TypeDependent - Whether this expression is type-dependent
+ /// TypeDependent - Whether this expression is type-dependent
/// (C++ [temp.dep.expr]).
bool TypeDependent : 1;
- /// ValueDependent - Whether this expression is value-dependent
+ /// ValueDependent - Whether this expression is value-dependent
/// (C++ [temp.dep.constexpr]).
bool ValueDependent : 1;
// FIXME: Eventually, this constructor should go away and we should
// require every subclass to provide type/value-dependence
// information.
- Expr(StmtClass SC, QualType T)
+ Expr(StmtClass SC, QualType T)
: Stmt(SC), TypeDependent(false), ValueDependent(false) {
- setType(T);
+ setType(T);
}
Expr(StmtClass SC, QualType T, bool TD, bool VD)
@@ -66,9 +67,18 @@ protected:
/// \brief Construct an empty expression.
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
-public:
+public:
+ /// \brief Increases the reference count for this expression.
+ ///
+ /// Invoke the Retain() operation when this expression
+ /// is being shared by another owner.
+ Expr *Retain() {
+ Stmt::Retain();
+ return this;
+ }
+
QualType getType() const { return TR; }
- void setType(QualType t) {
+ void setType(QualType t) {
// In C++, the type of an expression is always adjusted so that it
// will not have reference type an expression will never have
// reference type (C++ [expr]p6). Use
@@ -76,16 +86,16 @@ public:
// type. Additionally, inspect Expr::isLvalue to determine whether
// an expression that is adjusted in this manner should be
// considered an lvalue.
- assert((TR.isNull() || !TR->isReferenceType()) &&
+ assert((TR.isNull() || !TR->isReferenceType()) &&
"Expressions can't have reference type");
- TR = t;
+ TR = t;
}
/// isValueDependent - Determines whether this expression is
/// value-dependent (C++ [temp.dep.constexpr]). For example, the
/// array bound of "Chars" in the following example is
- /// value-dependent.
+ /// value-dependent.
/// @code
/// template<int Size, char (&Chars)[Size]> struct meta_string;
/// @endcode
@@ -100,7 +110,7 @@ public:
/// example, the expressions "x" and "x + y" are type-dependent in
/// the following code, but "y" is not type-dependent:
/// @code
- /// template<typename T>
+ /// template<typename T>
/// void add(T x, int y) {
/// x + y;
/// }
@@ -118,14 +128,14 @@ public:
/// getExprLoc - Return the preferred location for the arrow when diagnosing
/// a problem with a generic expression.
virtual SourceLocation getExprLoc() const { return getLocStart(); }
-
+
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in Loc and Ranges
/// with location to warn on and the source range[s] to report with the
/// warning.
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
SourceRange &R2) const;
-
+
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
/// incomplete type other than void. Nonarray expressions that can be lvalues:
/// - name, where name must be a variable
@@ -150,10 +160,10 @@ public:
// Same as above, but excluding checks for non-object and void types in C
isLvalueResult isLvalueInternal(ASTContext &Ctx) const;
-
+
/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
/// does not have an incomplete type, does not have a const-qualified type,
- /// and if it is a structure or union, does not have any member (including,
+ /// and if it is a structure or union, does not have any member (including,
/// recursively, any member or element of all contained aggregates or unions)
/// with a const-qualified type.
///
@@ -177,7 +187,7 @@ public:
};
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
SourceLocation *Loc = 0) const;
-
+
/// \brief If this expression refers to a bit-field, retrieve the
/// declaration of that bit-field.
FieldDecl *getBitField();
@@ -185,7 +195,7 @@ public:
const FieldDecl *getBitField() const {
return const_cast<Expr*>(this)->getBitField();
}
-
+
/// isIntegerConstantExpr - Return true if this expression is a valid integer
/// constant expression, and, if so, return its value in Result. If not a
/// valid i-c-e, return false and fill in Loc (if specified) with the location
@@ -200,16 +210,16 @@ public:
/// isConstantInitializer - Returns true if this expression is a constant
/// initializer, which can be emitted at compile-time.
bool isConstantInitializer(ASTContext &Ctx) const;
-
+
/// EvalResult is a struct with detailed info about an evaluated expression.
struct EvalResult {
/// Val - This is the value the expression can be folded to.
APValue Val;
-
+
/// HasSideEffects - Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
-
+
/// Diag - If the expression is unfoldable, then Diag contains a note
/// diagnostic indicating why it's not foldable. DiagLoc indicates a caret
/// position for the error, and DiagExpr is the expression that caused
@@ -221,7 +231,7 @@ public:
unsigned Diag;
const Expr *DiagExpr;
SourceLocation DiagLoc;
-
+
EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {}
};
@@ -239,25 +249,41 @@ public:
/// must be called on an expression that constant folds to an integer.
llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
- /// EvaluateAsLValue - Evaluate an expression to see if it's a valid LValue.
+ /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue
+ /// with link time known address.
bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const;
+ /// EvaluateAsAnyLValue - The same as EvaluateAsLValue, except that it
+ /// also succeeds on stack based, immutable address lvalues.
+ bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const;
+
+ /// \brief Enumeration used to describe how \c isNullPointerConstant()
+ /// should cope with value-dependent expressions.
+ enum NullPointerConstantValueDependence {
+ /// \brief Specifies that the expression should never be value-dependent.
+ NPC_NeverValueDependent = 0,
+
+ /// \brief Specifies that a value-dependent expression of integral or
+ /// dependent type should be considered a null pointer constant.
+ NPC_ValueDependentIsNull,
+
+ /// \brief Specifies that a value-dependent expression should be considered
+ /// to never be a null pointer constant.
+ NPC_ValueDependentIsNotNull
+ };
+
/// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an
/// integer constant expression with the value zero, or if this is one that is
/// cast to void*.
- bool isNullPointerConstant(ASTContext &Ctx) const;
-
- /// hasGlobalStorage - Return true if this expression has static storage
- /// duration. This means that the address of this expression is a link-time
- /// constant.
- bool hasGlobalStorage() const;
+ bool isNullPointerConstant(ASTContext &Ctx,
+ NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
- /// write barrier.
+ /// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
-
+
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
- /// its subexpression. If that subexpression is also a ParenExpr,
+ /// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
/// Otherwise, the method returns the current Expr.
Expr* IgnoreParens();
@@ -265,12 +291,12 @@ public:
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
/// or CastExprs, returning their operand.
Expr *IgnoreParenCasts();
-
+
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
/// value (including ptr->int casts of the same size). Strip off any
/// ParenExpr or CastExprs, returning their operand.
Expr *IgnoreParenNoopCasts(ASTContext &Ctx);
-
+
const Expr* IgnoreParens() const {
return const_cast<Expr*>(this)->IgnoreParens();
}
@@ -280,18 +306,18 @@ public:
const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const {
return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
}
-
+
static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs);
static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs);
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
- T->getStmtClass() <= lastExprConstant;
+ T->getStmtClass() <= lastExprConstant;
}
static bool classof(const Expr *) { return true; }
};
-
+
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
@@ -299,7 +325,7 @@ public:
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
/// enum, etc.
class DeclRefExpr : public Expr {
- NamedDecl *D;
+ NamedDecl *D;
SourceLocation Loc;
protected:
@@ -315,14 +341,14 @@ protected:
public:
// FIXME: Eventually, this constructor will go away and all clients
// will have to provide the type- and value-dependent flags.
- DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
+ DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
Expr(DeclRefExprClass, t), D(d), Loc(l) {}
- DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
+ DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
-
+
/// \brief Construct an empty declaration reference expression.
- explicit DeclRefExpr(EmptyShell Empty)
+ explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
NamedDecl *getDecl() { return D; }
@@ -332,14 +358,14 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass ||
T->getStmtClass() == CXXConditionDeclExprClass ||
- T->getStmtClass() == QualifiedDeclRefExprClass;
+ T->getStmtClass() == QualifiedDeclRefExprClass;
}
static bool classof(const DeclRefExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -353,38 +379,35 @@ public:
Function,
PrettyFunction
};
-
+
private:
SourceLocation Loc;
IdentType Type;
public:
- PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
- : Expr(PredefinedExprClass, type), Loc(l), Type(IT) {}
-
+ PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
+ : Expr(PredefinedExprClass, type, type->isDependentType(),
+ type->isDependentType()), Loc(l), Type(IT) {}
+
/// \brief Construct an empty predefined expression.
- explicit PredefinedExpr(EmptyShell Empty)
+ explicit PredefinedExpr(EmptyShell Empty)
: Expr(PredefinedExprClass, Empty) { }
- PredefinedExpr* Clone(ASTContext &C) const;
-
IdentType getIdentType() const { return Type; }
void setIdentType(IdentType IT) { Type = IT; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- // FIXME: The logic for computing the value of a predefined expr should go
- // into a method here that takes the inner-most code decl (a block, function
- // or objc method) that the expr lives in. This would allow sema and codegen
- // to be consistent for things like sizeof(__func__) etc.
-
+ static std::string ComputeName(ASTContext &Context, IdentType IT,
+ const Decl *CurrentDecl);
+
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == PredefinedExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedExprClass;
}
static bool classof(const PredefinedExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -394,7 +417,7 @@ class IntegerLiteral : public Expr {
llvm::APInt Value;
SourceLocation Loc;
public:
- // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
: Expr(IntegerLiteralClass, type), Value(V), Loc(l) {
@@ -402,11 +425,9 @@ public:
}
/// \brief Construct an empty integer literal.
- explicit IntegerLiteral(EmptyShell Empty)
+ explicit IntegerLiteral(EmptyShell Empty)
: Expr(IntegerLiteralClass, Empty) { }
- IntegerLiteral* Clone(ASTContext &C) const;
-
const llvm::APInt &getValue() const { return Value; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
@@ -416,11 +437,11 @@ public:
void setValue(const llvm::APInt &Val) { Value = Val; }
void setLocation(SourceLocation Location) { Loc = Location; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == IntegerLiteralClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IntegerLiteralClass;
}
static bool classof(const IntegerLiteral *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -439,21 +460,19 @@ public:
/// \brief Construct an empty character literal.
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
- CharacterLiteral* Clone(ASTContext &C) const;
-
- SourceLocation getLoc() const { return Loc; }
+ SourceLocation getLocation() const { return Loc; }
bool isWide() const { return IsWide; }
-
+
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
+
unsigned getValue() const { return Value; }
void setLocation(SourceLocation Location) { Loc = Location; }
void setWide(bool W) { IsWide = W; }
void setValue(unsigned Val) { Value = Val; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CharacterLiteralClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CharacterLiteralClass;
}
static bool classof(const CharacterLiteral *) { return true; }
@@ -467,16 +486,14 @@ class FloatingLiteral : public Expr {
bool IsExact : 1;
SourceLocation Loc;
public:
- FloatingLiteral(const llvm::APFloat &V, bool isexact,
+ FloatingLiteral(const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {}
+ : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {}
/// \brief Construct an empty floating-point literal.
- explicit FloatingLiteral(EmptyShell Empty)
+ explicit FloatingLiteral(EmptyShell Empty)
: Expr(FloatingLiteralClass, Empty), Value(0.0) { }
- FloatingLiteral* Clone(ASTContext &C) const;
-
const llvm::APFloat &getValue() const { return Value; }
void setValue(const llvm::APFloat &Val) { Value = Val; }
@@ -487,7 +504,7 @@ public:
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
double getValueAsApproximateDouble() const;
-
+
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -495,14 +512,14 @@ public:
// into a method here that takes the inner-most code decl (a block, function
// or objc method) that the expr lives in. This would allow sema and codegen
// to be consistent for things like sizeof(__func__) etc.
-
+
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == FloatingLiteralClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FloatingLiteralClass;
}
static bool classof(const FloatingLiteral *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -518,23 +535,21 @@ class ImaginaryLiteral : public Expr {
public:
ImaginaryLiteral(Expr *val, QualType Ty)
: Expr(ImaginaryLiteralClass, Ty), Val(val) {}
-
+
/// \brief Build an empty imaginary literal.
- explicit ImaginaryLiteral(EmptyShell Empty)
+ explicit ImaginaryLiteral(EmptyShell Empty)
: Expr(ImaginaryLiteralClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- ImaginaryLiteral* Clone(ASTContext &C) const;
-
virtual SourceRange getSourceRange() const { return Val->getSourceRange(); }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ImaginaryLiteralClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImaginaryLiteralClass;
}
static bool classof(const ImaginaryLiteral *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -564,6 +579,10 @@ class StringLiteral : public Expr {
SourceLocation TokLocs[1];
StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {}
+
+protected:
+ virtual void DoDestroy(ASTContext &C);
+
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
@@ -572,7 +591,7 @@ public:
const SourceLocation *Loc, unsigned NumStrs);
/// Simple constructor for string literals made from one token.
- static StringLiteral *Create(ASTContext &C, const char *StrData,
+ static StringLiteral *Create(ASTContext &C, const char *StrData,
unsigned ByteLength,
bool Wide, QualType Ty, SourceLocation Loc) {
return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1);
@@ -581,33 +600,35 @@ public:
/// \brief Construct an empty string literal.
static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
- StringLiteral* Clone(ASTContext &C) const;
- void Destroy(ASTContext &C);
-
+ llvm::StringRef getString() const {
+ return llvm::StringRef(StrData, ByteLength);
+ }
+ // FIXME: These are deprecated, replace with StringRef.
const char *getStrData() const { return StrData; }
unsigned getByteLength() const { return ByteLength; }
/// \brief Sets the string data to the given string data.
- void setStrData(ASTContext &C, const char *Str, unsigned Len);
+ void setString(ASTContext &C, llvm::StringRef Str);
bool isWide() const { return IsWide; }
void setWide(bool W) { IsWide = W; }
bool containsNonAsciiOrNull() const {
- for (unsigned i = 0; i < getByteLength(); ++i)
- if (!isascii(getStrData()[i]) || !getStrData()[i])
+ llvm::StringRef Str = getString();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ if (!isascii(Str[i]) || !Str[i])
return true;
return false;
}
/// getNumConcatenated - Get the number of string literal tokens that were
/// concatenated in translation phase #6 to form this string literal.
unsigned getNumConcatenated() const { return NumConcatenated; }
-
+
SourceLocation getStrTokenLoc(unsigned TokNum) const {
assert(TokNum < NumConcatenated && "Invalid tok number");
return TokLocs[TokNum];
}
- void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
+ void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
assert(TokNum < NumConcatenated && "Invalid tok number");
TokLocs[TokNum] = L;
}
@@ -616,14 +637,14 @@ public:
tokloc_iterator tokloc_begin() const { return TokLocs; }
tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == StringLiteralClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StringLiteralClass;
}
static bool classof(const StringLiteral *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -637,11 +658,11 @@ class ParenExpr : public Expr {
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(),
- val->isTypeDependent(), val->isValueDependent()),
+ val->isTypeDependent(), val->isValueDependent()),
L(l), R(r), Val(val) {}
-
+
/// \brief Construct an empty parenthesized expression.
- explicit ParenExpr(EmptyShell Empty)
+ explicit ParenExpr(EmptyShell Empty)
: Expr(ParenExprClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
@@ -658,11 +679,11 @@ public:
SourceLocation getRParen() const { return R; }
void setRParen(SourceLocation Loc) { R = Loc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ParenExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenExprClass;
}
static bool classof(const ParenExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -680,7 +701,7 @@ public:
/// later returns zero in the type of the operand.
///
/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
-/// subexpression is a compound literal with the various MemberExpr and
+/// subexpression is a compound literal with the various MemberExpr and
/// ArraySubscriptExpr's applied to it.
///
class UnaryOperator : public Expr {
@@ -700,16 +721,16 @@ private:
Stmt *Val;
Opcode Opc;
SourceLocation Loc;
-public:
+public:
UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
: Expr(UnaryOperatorClass, type,
input->isTypeDependent() && opc != OffsetOf,
- input->isValueDependent()),
+ input->isValueDependent()),
Val(input), Opc(opc), Loc(l) {}
/// \brief Build an empty unary operator.
- explicit UnaryOperator(EmptyShell Empty)
+ explicit UnaryOperator(EmptyShell Empty)
: Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { }
Opcode getOpcode() const { return Opc; }
@@ -738,7 +759,8 @@ public:
bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
bool isOffsetOfOp() const { return Opc == OffsetOf; }
static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
-
+ bool isArithmeticOp() const { return isArithmeticOp(Opc); }
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
static const char *getOpcodeStr(Opcode Op);
@@ -758,12 +780,12 @@ public:
return SourceRange(Loc, Val->getLocEnd());
}
virtual SourceLocation getExprLoc() const { return Loc; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == UnaryOperatorClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryOperatorClass;
}
static bool classof(const UnaryOperator *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -779,8 +801,12 @@ class SizeOfAlignOfExpr : public Expr {
Stmt *Ex;
} Argument;
SourceLocation OpLoc, RParenLoc;
+
+protected:
+ virtual void DoDestroy(ASTContext& C);
+
public:
- SizeOfAlignOfExpr(bool issizeof, QualType T,
+ SizeOfAlignOfExpr(bool issizeof, QualType T,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType,
@@ -791,7 +817,7 @@ public:
Argument.Ty = T.getAsOpaquePtr();
}
- SizeOfAlignOfExpr(bool issizeof, Expr *E,
+ SizeOfAlignOfExpr(bool issizeof, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType,
@@ -806,8 +832,6 @@ public:
explicit SizeOfAlignOfExpr(EmptyShell Empty)
: Expr(SizeOfAlignOfExprClass, Empty) { }
- virtual void Destroy(ASTContext& C);
-
bool isSizeOf() const { return isSizeof; }
void setSizeof(bool S) { isSizeof = S; }
@@ -825,9 +849,9 @@ public:
}
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
- void setArgument(QualType T) {
- Argument.Ty = T.getAsOpaquePtr();
- isType = true;
+ void setArgument(QualType T) {
+ Argument.Ty = T.getAsOpaquePtr();
+ isType = true;
}
/// Gets the argument type, or the type of the argument expression, whichever
@@ -846,11 +870,11 @@ public:
return SourceRange(OpLoc, RParenLoc);
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == SizeOfAlignOfExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfAlignOfExprClass;
}
static bool classof(const SizeOfAlignOfExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -863,7 +887,7 @@ public:
/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
enum { LHS, RHS, END_EXPR=2 };
- Stmt* SubExprs[END_EXPR];
+ Stmt* SubExprs[END_EXPR];
SourceLocation RBracketLoc;
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
@@ -875,7 +899,7 @@ public:
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
-
+
/// \brief Create an empty array subscript expression.
explicit ArraySubscriptExpr(EmptyShell Shell)
: Expr(ArraySubscriptExprClass, Shell) { }
@@ -896,37 +920,37 @@ public:
Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
-
- Expr *getBase() {
+
+ Expr *getBase() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
-
- const Expr *getBase() const {
+
+ const Expr *getBase() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
-
- Expr *getIdx() {
+
+ Expr *getIdx() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
-
+
const Expr *getIdx() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
- }
-
- virtual SourceRange getSourceRange() const {
+ }
+
+ virtual SourceRange getSourceRange() const {
return SourceRange(getLHS()->getLocStart(), RBracketLoc);
}
-
+
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
virtual SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ArraySubscriptExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySubscriptExprClass;
}
static bool classof(const ArraySubscriptExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -934,9 +958,9 @@ public:
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
-/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
+/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
-/// results in a function call. For example, CXXOperatorCallExpr is
+/// results in a function call. For example, CXXOperatorCallExpr is
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
@@ -944,31 +968,37 @@ class CallExpr : public Expr {
Stmt **SubExprs;
unsigned NumArgs;
SourceLocation RParenLoc;
-
+
protected:
// This version of the constructor is for derived classes.
CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
QualType t, SourceLocation rparenloc);
-
+
+ virtual void DoDestroy(ASTContext& C);
+
public:
- CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
+ CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation rparenloc);
-
+
/// \brief Build an empty call expression.
- CallExpr(ASTContext &C, EmptyShell Empty);
+ CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
~CallExpr() {}
-
- void Destroy(ASTContext& C);
-
+
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
-
+
+ /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
+ FunctionDecl *getDirectCallee();
+ const FunctionDecl *getDirectCallee() const {
+ return const_cast<CallExpr*>(this)->getDirectCallee();
+ }
+
/// getNumArgs - Return the number of actual arguments to this call.
///
unsigned getNumArgs() const { return NumArgs; }
-
+
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
@@ -978,26 +1008,26 @@ public:
assert(Arg < NumArgs && "Arg access out of range!");
return cast<Expr>(SubExprs[Arg+ARGS_START]);
}
-
+
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
SubExprs[Arg+ARGS_START] = ArgExpr;
}
-
+
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
void setNumArgs(ASTContext& C, unsigned NumArgs);
-
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
-
+
arg_iterator arg_begin() { return SubExprs+ARGS_START; }
arg_iterator arg_end() { return SubExprs+ARGS_START+getNumArgs(); }
const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; }
const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();}
-
+
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
@@ -1005,23 +1035,23 @@ public:
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
unsigned isBuiltinCall(ASTContext &Context) const;
-
- /// getCallReturnType - Get the return type of the call expr. This is not
- /// always the type of the expr itself, if the return type is a reference
+
+ /// getCallReturnType - Get the return type of the call expr. This is not
+ /// always the type of the expr itself, if the return type is a reference
/// type.
QualType getCallReturnType() const;
-
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ virtual SourceRange getSourceRange() const {
return SourceRange(getCallee()->getLocStart(), RParenLoc);
}
-
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CallExprClass ||
T->getStmtClass() == CXXOperatorCallExprClass ||
- T->getStmtClass() == CXXMemberCallExprClass;
+ T->getStmtClass() == CXXMemberCallExprClass;
}
static bool classof(const CallExpr *) { return true; }
static bool classof(const CXXOperatorCallExpr *) { return true; }
@@ -1032,31 +1062,131 @@ public:
virtual child_iterator child_end();
};
+/// \brief Represents the qualifier that may precede a C++ name, e.g., the
+/// "std::" in "std::sort".
+struct NameQualifier {
+ /// \brief The nested name specifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The source range covered by the nested name specifier.
+ SourceRange Range;
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+struct ExplicitTemplateArgumentList {
+ /// \brief The source location of the left angle bracket ('<');
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>');
+ SourceLocation RAngleLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ /// The actual template arguments (if any) are stored after the
+ /// ExplicitTemplateArgumentList structure.
+ unsigned NumTemplateArgs;
+
+ /// \brief Retrieve the template arguments
+ TemplateArgument *getTemplateArgs() {
+ return reinterpret_cast<TemplateArgument *> (this + 1);
+ }
+
+ /// \brief Retrieve the template arguments
+ const TemplateArgument *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgument *> (this + 1);
+ }
+};
+
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr : public Expr {
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
-
+
/// MemberDecl - This is the decl being referenced by the field/member name.
/// In X.F, this is the decl referenced by F.
NamedDecl *MemberDecl;
-
+
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
-
+
/// IsArrow - True if this is "X->F", false if this is "X.F".
- bool IsArrow;
+ bool IsArrow : 1;
+
+ /// \brief True if this member expression used a nested-name-specifier to
+ /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier
+ /// structure is allocated immediately after the MemberExpr.
+ bool HasQualifier : 1;
+
+ /// \brief True if this member expression specified a template argument list
+ /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
+ /// structure (and its TemplateArguments) are allocated immediately after
+ /// the MemberExpr or, if the member expression also has a qualifier, after
+ /// the NameQualifier structure.
+ bool HasExplicitTemplateArgumentList : 1;
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ NameQualifier *getMemberQualifier() {
+ if (!HasQualifier)
+ return 0;
+
+ return reinterpret_cast<NameQualifier *> (this + 1);
+ }
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ const NameQualifier *getMemberQualifier() const {
+ return const_cast<MemberExpr *>(this)->getMemberQualifier();
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ if (!HasQualifier)
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getMemberQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
+ }
+
+ MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
+ SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
+ bool has_explicit, SourceLocation langle,
+ const TemplateArgument *targs, unsigned numtargs,
+ SourceLocation rangle, QualType ty);
+
public:
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
- QualType ty)
- : Expr(MemberExprClass, ty,
+ QualType ty)
+ : Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
- Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {}
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
+ HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
/// \brief Build an empty member reference expression.
- explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { }
+ explicit MemberExpr(EmptyShell Empty)
+ : Expr(MemberExprClass, Empty), HasQualifier(false),
+ HasExplicitTemplateArgumentList(false) { }
+
+ static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
+ NestedNameSpecifier *qual, SourceRange qualrange,
+ NamedDecl *memberdecl,
+ SourceLocation l,
+ bool has_explicit,
+ SourceLocation langle,
+ const TemplateArgument *targs,
+ unsigned numtargs,
+ SourceLocation rangle,
+ QualType ty);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -1068,6 +1198,73 @@ public:
NamedDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(NamedDecl *D) { MemberDecl = D; }
+ /// \brief Determines whether this member expression actually had
+ /// a C++ nested-name-specifier prior to the name of the member, e.g.,
+ /// x->Base::foo.
+ bool hasQualifier() const { return HasQualifier; }
+
+ /// \brief If the member name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the member name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const {
+ if (!HasQualifier)
+ return SourceRange();
+
+ return getMemberQualifier()->Range;
+ }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const {
+ if (!HasQualifier)
+ return 0;
+
+ return getMemberQualifier()->NNS;
+ }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgumentList() {
+ return HasExplicitTemplateArgumentList;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgument *getTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgumentList()->getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->RAngleLoc;
+ }
+
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }
@@ -1079,25 +1276,29 @@ public:
virtual SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
+ SourceLocation EndLoc = MemberLoc;
+ if (HasExplicitTemplateArgumentList)
+ EndLoc = getRAngleLoc();
+
SourceLocation BaseLoc = getBase()->getLocStart();
if (BaseLoc.isInvalid())
- return SourceRange(MemberLoc, MemberLoc);
- return SourceRange(BaseLoc, MemberLoc);
+ return SourceRange(MemberLoc, EndLoc);
+ return SourceRange(BaseLoc, EndLoc);
}
-
+
virtual SourceLocation getExprLoc() const { return MemberLoc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == MemberExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MemberExprClass;
}
static bool classof(const MemberExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-/// CompoundLiteralExpr - [C99 6.5.2.5]
+/// CompoundLiteralExpr - [C99 6.5.2.5]
///
class CompoundLiteralExpr : public Expr {
/// LParenLoc - If non-null, this is the location of the left paren in a
@@ -1111,7 +1312,7 @@ public:
bool fileScope)
: Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init),
FileScope(fileScope) {}
-
+
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
: Expr(CompoundLiteralExprClass, Empty) { }
@@ -1135,11 +1336,11 @@ public:
return SourceRange(LParenLoc, Init->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CompoundLiteralExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundLiteralExprClass;
}
static bool classof(const CompoundLiteralExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1150,28 +1351,85 @@ public:
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
+public:
+ /// CastKind - the kind of cast this represents.
+ enum CastKind {
+ /// CK_Unknown - Unknown cast kind.
+ /// FIXME: The goal is to get rid of this and make all casts have a
+ /// kind so that the AST client doesn't have to try to figure out what's
+ /// going on.
+ CK_Unknown,
+
+ /// CK_BitCast - Used for reinterpret_cast.
+ CK_BitCast,
+
+ /// CK_NoOp - Used for const_cast.
+ CK_NoOp,
+
+ /// CK_DerivedToBase - Derived to base class casts.
+ CK_DerivedToBase,
+
+ /// CK_Dynamic - Dynamic cast.
+ CK_Dynamic,
+
+ /// CK_ToUnion - Cast to union (GCC extension).
+ CK_ToUnion,
+
+ /// CK_ArrayToPointerDecay - Array to pointer decay.
+ CK_ArrayToPointerDecay,
+
+ // CK_FunctionToPointerDecay - Function to pointer decay.
+ CK_FunctionToPointerDecay,
+
+ /// CK_NullToMemberPointer - Null pointer to member pointer.
+ CK_NullToMemberPointer,
+
+ /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
+ /// member pointer in derived class.
+ CK_BaseToDerivedMemberPointer,
+
+ /// CK_UserDefinedConversion - Conversion using a user defined type
+ /// conversion function.
+ CK_UserDefinedConversion,
+
+ /// CK_ConstructorConversion - Conversion by constructor
+ CK_ConstructorConversion,
+
+ /// CK_IntegralToPointer - Integral to pointer
+ CK_IntegralToPointer,
+
+ /// CK_PointerToIntegral - Pointer to integral
+ CK_PointerToIntegral
+ };
+
+private:
+ CastKind Kind;
Stmt *Op;
protected:
- CastExpr(StmtClass SC, QualType ty, Expr *op) :
+ CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op) :
Expr(SC, ty,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
ty->isDependentType(),
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
- ty->isDependentType() || (op && op->isValueDependent())),
- Op(op) {}
-
+ ty->isDependentType() || (op && op->isValueDependent())),
+ Kind(kind), Op(op) {}
+
/// \brief Construct an empty cast.
- CastExpr(StmtClass SC, EmptyShell Empty)
+ CastExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty) { }
-
+
public:
+ CastKind getCastKind() const { return Kind; }
+ void setCastKind(CastKind K) { Kind = K; }
+ const char *getCastKindName() const;
+
Expr *getSubExpr() { return cast<Expr>(Op); }
const Expr *getSubExpr() const { return cast<Expr>(Op); }
void setSubExpr(Expr *E) { Op = E; }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
StmtClass SC = T->getStmtClass();
if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
return true;
@@ -1182,7 +1440,7 @@ public:
return false;
}
static bool classof(const CastExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1200,7 +1458,7 @@ public:
/// @code
/// class Base { };
/// class Derived : public Base { };
-/// void f(Derived d) {
+/// void f(Derived d) {
/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
/// }
/// @endcode
@@ -1209,11 +1467,11 @@ class ImplicitCastExpr : public CastExpr {
bool LvalueCast;
public:
- ImplicitCastExpr(QualType ty, Expr *op, bool Lvalue) :
- CastExpr(ImplicitCastExprClass, ty, op), LvalueCast(Lvalue) { }
+ ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, bool Lvalue) :
+ CastExpr(ImplicitCastExprClass, ty, kind, op), LvalueCast(Lvalue) { }
/// \brief Construct an empty implicit cast.
- explicit ImplicitCastExpr(EmptyShell Shell)
+ explicit ImplicitCastExpr(EmptyShell Shell)
: CastExpr(ImplicitCastExprClass, Shell) { }
@@ -1227,14 +1485,14 @@ public:
/// setLvalueCast - Set whether this cast produces an lvalue.
void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ImplicitCastExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitCastExprClass;
}
static bool classof(const ImplicitCastExpr *) { return true; }
};
/// ExplicitCastExpr - An explicit cast written in the source
-/// code.
+/// code.
///
/// This class is effectively an abstract class, because it provides
/// the basic representation of an explicitly-written cast without
@@ -1255,11 +1513,12 @@ class ExplicitCastExpr : public CastExpr {
QualType TypeAsWritten;
protected:
- ExplicitCastExpr(StmtClass SC, QualType exprTy, Expr *op, QualType writtenTy)
- : CastExpr(SC, exprTy, op), TypeAsWritten(writtenTy) {}
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
+ Expr *op, QualType writtenTy)
+ : CastExpr(SC, exprTy, kind, op), TypeAsWritten(writtenTy) {}
/// \brief Construct an empty explicit cast.
- ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
: CastExpr(SC, Shell) { }
public:
@@ -1268,7 +1527,7 @@ public:
QualType getTypeAsWritten() const { return TypeAsWritten; }
void setTypeAsWritten(QualType T) { TypeAsWritten = T; }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
StmtClass SC = T->getStmtClass();
if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass)
return true;
@@ -1287,13 +1546,13 @@ class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
public:
- CStyleCastExpr(QualType exprTy, Expr *op, QualType writtenTy,
- SourceLocation l, SourceLocation r) :
- ExplicitCastExpr(CStyleCastExprClass, exprTy, op, writtenTy),
+ CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, QualType writtenTy,
+ SourceLocation l, SourceLocation r) :
+ ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy),
LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
- explicit CStyleCastExpr(EmptyShell Shell)
+ explicit CStyleCastExpr(EmptyShell Shell)
: ExplicitCastExpr(CStyleCastExprClass, Shell) { }
SourceLocation getLParenLoc() const { return LPLoc; }
@@ -1305,8 +1564,8 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CStyleCastExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CStyleCastExprClass;
}
static bool classof(const CStyleCastExpr *) { return true; }
};
@@ -1358,22 +1617,22 @@ private:
Stmt* SubExprs[END_EXPR];
Opcode Opc;
SourceLocation OpLoc;
-public:
-
+public:
+
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
SourceLocation opLoc)
: Expr(BinaryOperatorClass, ResTy,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent()),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
- assert(!isCompoundAssignmentOp() &&
+ assert(!isCompoundAssignmentOp() &&
"Use ArithAssignBinaryOperator for compound assignments");
}
/// \brief Construct an empty binary operator.
- explicit BinaryOperator(EmptyShell Empty)
+ explicit BinaryOperator(EmptyShell Empty)
: Expr(BinaryOperatorClass, Empty), Opc(Comma) { }
SourceLocation getOperatorLoc() const { return OpLoc; }
@@ -1390,7 +1649,7 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
}
-
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
static const char *getOpcodeStr(Opcode Op);
@@ -1412,19 +1671,19 @@ public:
static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
bool isRelationalOp() const { return isRelationalOp(Opc); }
- static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
+ static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
bool isEqualityOp() const { return isEqualityOp(Opc); }
-
+
static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
bool isLogicalOp() const { return isLogicalOp(Opc); }
bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; }
bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;}
bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; }
-
- static bool classof(const Stmt *S) {
+
+ static bool classof(const Stmt *S) {
return S->getStmtClass() == BinaryOperatorClass ||
- S->getStmtClass() == CompoundAssignOperatorClass;
+ S->getStmtClass() == CompoundAssignOperatorClass;
}
static bool classof(const BinaryOperator *) { return true; }
@@ -1440,7 +1699,7 @@ protected:
SubExprs[RHS] = rhs;
}
- BinaryOperator(StmtClass SC, EmptyShell Empty)
+ BinaryOperator(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Opc(MulAssign) { }
};
@@ -1461,7 +1720,7 @@ public:
: BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true),
ComputationLHSType(CompLHSType),
ComputationResultType(CompResultType) {
- assert(isCompoundAssignmentOp() &&
+ assert(isCompoundAssignmentOp() &&
"Only should be used for compound assignments");
}
@@ -1479,8 +1738,8 @@ public:
void setComputationResultType(QualType T) { ComputationResultType = T; }
static bool classof(const CompoundAssignOperator *) { return true; }
- static bool classof(const Stmt *S) {
- return S->getStmtClass() == CompoundAssignOperatorClass;
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == CompoundAssignOperatorClass;
}
};
@@ -1490,16 +1749,20 @@ public:
class ConditionalOperator : public Expr {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+ SourceLocation QuestionLoc, ColonLoc;
public:
- ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs, QualType t)
+ ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
+ SourceLocation CLoc, Expr *rhs, QualType t)
: Expr(ConditionalOperatorClass, t,
// FIXME: the type of the conditional operator doesn't
// depend on the type of the conditional, but the standard
// seems to imply that it could. File a bug!
((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())),
- (cond->isValueDependent() ||
+ (cond->isValueDependent() ||
(lhs && lhs->isValueDependent()) ||
- (rhs && rhs->isValueDependent()))) {
+ (rhs && rhs->isValueDependent()))),
+ QuestionLoc(QLoc),
+ ColonLoc(CLoc) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -1519,29 +1782,35 @@ public:
// will be the same as getLHS() except a GCC extension allows the left
// subexpression to be omitted, and instead of the condition be returned.
// e.g: x ?: y is shorthand for x ? x : y, except that the expression "x"
- // is only evaluated once.
+ // is only evaluated once.
Expr *getTrueExpr() const {
return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]);
}
-
+
// getTrueExpr - Return the subexpression representing the value of the ?:
// expression if the condition evaluates to false. This is the same as getRHS.
Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
-
+
Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
+ SourceLocation getQuestionLoc() const { return QuestionLoc; }
+ void setQuestionLoc(SourceLocation L) { QuestionLoc = L; }
+
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
virtual SourceRange getSourceRange() const {
return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ConditionalOperatorClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass;
}
static bool classof(const ConditionalOperator *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1555,9 +1824,9 @@ public:
AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
QualType t)
: Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
-
+
/// \brief Build an empty address of a label expression.
- explicit AddrLabelExpr(EmptyShell Empty)
+ explicit AddrLabelExpr(EmptyShell Empty)
: Expr(AddrLabelExprClass, Empty) { }
SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
@@ -1568,15 +1837,15 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(AmpAmpLoc, LabelLoc);
}
-
+
LabelStmt *getLabel() const { return Label; }
void setLabel(LabelStmt *S) { Label = S; }
static bool classof(const Stmt *T) {
- return T->getStmtClass() == AddrLabelExprClass;
+ return T->getStmtClass() == AddrLabelExprClass;
}
static bool classof(const AddrLabelExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1592,7 +1861,7 @@ public:
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
-
+
/// \brief Build an empty statement expression.
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
@@ -1603,17 +1872,17 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(LParenLoc, RParenLoc);
}
-
+
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
+
static bool classof(const Stmt *T) {
- return T->getStmtClass() == StmtExprClass;
+ return T->getStmtClass() == StmtExprClass;
}
static bool classof(const StmtExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1628,8 +1897,8 @@ class TypesCompatibleExpr : public Expr {
QualType Type2;
SourceLocation BuiltinLoc, RParenLoc;
public:
- TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
- QualType t1, QualType t2, SourceLocation RP) :
+ TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
+ QualType t1, QualType t2, SourceLocation RP) :
Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2),
BuiltinLoc(BLoc), RParenLoc(RP) {}
@@ -1641,21 +1910,21 @@ public:
void setArgType1(QualType T) { Type1 = T; }
QualType getArgType2() const { return Type2; }
void setArgType2(QualType T) { Type2 = T; }
-
+
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
-
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == TypesCompatibleExprClass;
+ return T->getStmtClass() == TypesCompatibleExprClass;
}
static bool classof(const TypesCompatibleExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1677,25 +1946,28 @@ class ShuffleVectorExpr : public Expr {
Stmt **SubExprs;
unsigned NumExprs;
+protected:
+ virtual void DoDestroy(ASTContext &C);
+
public:
- ShuffleVectorExpr(Expr **args, unsigned nexpr,
- QualType Type, SourceLocation BLoc,
- SourceLocation RP) :
+ ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
+ QualType Type, SourceLocation BLoc,
+ SourceLocation RP) :
Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc),
RParenLoc(RP), NumExprs(nexpr) {
-
- SubExprs = new Stmt*[nexpr];
+
+ SubExprs = new (C) Stmt*[nexpr];
for (unsigned i = 0; i < nexpr; i++)
SubExprs[i] = args[i];
}
/// \brief Build an empty vector-shuffle expression.
- explicit ShuffleVectorExpr(EmptyShell Empty)
+ explicit ShuffleVectorExpr(EmptyShell Empty)
: Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
-
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -1703,19 +1975,17 @@ public:
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == ShuffleVectorExprClass;
+ return T->getStmtClass() == ShuffleVectorExprClass;
}
static bool classof(const ShuffleVectorExpr *) { return true; }
-
- ~ShuffleVectorExpr() {
- delete [] SubExprs;
- }
-
+
+ ~ShuffleVectorExpr() {}
+
/// getNumSubExprs - Return the size of the SubExprs array. This includes the
/// constant expression, the actual arguments passed in, and the function
/// pointers.
unsigned getNumSubExprs() const { return NumExprs; }
-
+
/// getExpr - Return the Expr at the specified index.
Expr *getExpr(unsigned Index) {
assert((Index < NumExprs) && "Arg access out of range!");
@@ -1726,20 +1996,20 @@ public:
return cast<Expr>(SubExprs[Index]);
}
- void setExprs(Expr ** Exprs, unsigned NumExprs);
+ void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs);
unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) {
assert((N < NumExprs - 2) && "Shuffle idx out of range!");
return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue();
}
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
-/// This AST node is similar to the conditional operator (?:) in C, with
+/// This AST node is similar to the conditional operator (?:) in C, with
/// the following exceptions:
/// - the test expression must be a integer constant expression.
/// - the expression returned acts like the chosen subexpression in every
@@ -1753,13 +2023,13 @@ class ChooseExpr : public Expr {
SourceLocation BuiltinLoc, RParenLoc;
public:
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
- SourceLocation RP)
- : Expr(ChooseExprClass, t),
+ SourceLocation RP, bool TypeDependent, bool ValueDependent)
+ : Expr(ChooseExprClass, t, TypeDependent, ValueDependent),
BuiltinLoc(BLoc), RParenLoc(RP) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
- }
+ }
/// \brief Build an empty __builtin_choose_expr.
explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }
@@ -1783,7 +2053,7 @@ public:
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
-
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -1791,10 +2061,10 @@ public:
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == ChooseExprClass;
+ return T->getStmtClass() == ChooseExprClass;
}
static bool classof(const ChooseExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1811,14 +2081,12 @@ class GNUNullExpr : public Expr {
SourceLocation TokenLoc;
public:
- GNUNullExpr(QualType Ty, SourceLocation Loc)
+ GNUNullExpr(QualType Ty, SourceLocation Loc)
: Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { }
/// \brief Build an empty GNU __null expression.
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
- GNUNullExpr* Clone(ASTContext &C) const;
-
/// getTokenLocation - The location of the __null token.
SourceLocation getTokenLocation() const { return TokenLoc; }
void setTokenLocation(SourceLocation L) { TokenLoc = L; }
@@ -1827,10 +2095,10 @@ public:
return SourceRange(TokenLoc);
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == GNUNullExprClass;
+ return T->getStmtClass() == GNUNullExprClass;
}
static bool classof(const GNUNullExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -1846,7 +2114,7 @@ public:
Val(e),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
-
+
/// \brief Create an empty __builtin_va_start expression.
explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
@@ -1856,23 +2124,23 @@ public:
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
-
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
virtual SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
- }
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == VAArgExprClass;
}
static bool classof(const VAArgExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ virtual child_iterator child_end();
};
-
+
/// @brief Describes an C or C++ initializer list.
///
/// InitListExpr describes an initializer list, which can be used to
@@ -1911,9 +2179,10 @@ public:
/// return NULL, indicating that the current initializer list also
/// serves as its syntactic form.
class InitListExpr : public Expr {
+ // FIXME: Eliminate this vector in favor of ASTContext allocation
std::vector<Stmt *> InitExprs;
SourceLocation LBraceLoc, RBraceLoc;
-
+
/// Contains the initializer list that describes the syntactic form
/// written in the source code.
InitListExpr *SyntacticForm;
@@ -1932,27 +2201,27 @@ public:
/// \brief Build an empty initializer list.
explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty) { }
-
+
unsigned getNumInits() const { return InitExprs.size(); }
-
- const Expr* getInit(unsigned Init) const {
+
+ const Expr* getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
-
- Expr* getInit(unsigned Init) {
+
+ Expr* getInit(unsigned Init) {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
-
- void setInit(unsigned Init, Expr *expr) {
+
+ void setInit(unsigned Init, Expr *expr) {
assert(Init < getNumInits() && "Initializer access out of range!");
InitExprs[Init] = expr;
}
/// \brief Reserve space for some number of initializers.
void reserveInits(unsigned NumInits);
-
+
/// @brief Specify the number of initializers
///
/// If there are more than @p NumInits initializers, the remaining
@@ -1984,7 +2253,7 @@ public:
bool isExplicit() {
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
-
+
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
@@ -1993,30 +2262,30 @@ public:
/// @brief Retrieve the initializer list that describes the
/// syntactic form of the initializer.
///
- ///
+ ///
InitListExpr *getSyntacticForm() const { return SyntacticForm; }
void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; }
bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; }
- void sawArrayRangeDesignator(bool ARD = true) {
+ void sawArrayRangeDesignator(bool ARD = true) {
HadArrayRangeDesignator = ARD;
}
virtual SourceRange getSourceRange() const {
return SourceRange(LBraceLoc, RBraceLoc);
- }
+ }
static bool classof(const Stmt *T) {
- return T->getStmtClass() == InitListExprClass;
+ return T->getStmtClass() == InitListExprClass;
}
static bool classof(const InitListExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
+
typedef std::vector<Stmt *>::iterator iterator;
typedef std::vector<Stmt *>::reverse_iterator reverse_iterator;
-
+
iterator begin() { return InitExprs.begin(); }
iterator end() { return InitExprs.end(); }
reverse_iterator rbegin() { return InitExprs.rbegin(); }
@@ -2030,7 +2299,7 @@ public:
/// designators, or GNU array-range designators) followed by an
/// expression that initializes the field or element(s) that the
/// designators refer to. For example, given:
-///
+///
/// @code
/// struct point {
/// double x;
@@ -2070,7 +2339,7 @@ private:
unsigned NumSubExprs : 16;
- DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+ DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc, bool GNUSyntax,
Expr **IndexExprs, unsigned NumIndexExprs,
@@ -2080,6 +2349,9 @@ private:
: Expr(DesignatedInitExprClass, EmptyShell()),
NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { }
+protected:
+ virtual void DoDestroy(ASTContext &C);
+
public:
/// A field designator, e.g., ".x".
struct FieldDesignator {
@@ -2090,10 +2362,10 @@ public:
/// IdentifierInfo*. After semantic analysis has resolved that
/// name, the field designator will instead store a FieldDecl*.
uintptr_t NameOrField;
-
+
/// The location of the '.' in the designated initializer.
unsigned DotLoc;
-
+
/// The location of the field name in the designated initializer.
unsigned FieldLoc;
};
@@ -2109,7 +2381,7 @@ public:
/// indices. Only valid for GNU array-range designators.
unsigned EllipsisLoc;
/// The location of the ']' terminating the array range designator.
- unsigned RBracketLoc;
+ unsigned RBracketLoc;
};
/// @brief Represents a single C99 designator.
@@ -2138,8 +2410,8 @@ public:
Designator() {}
/// @brief Initializes a field designator.
- Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
- SourceLocation FieldLoc)
+ Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
+ SourceLocation FieldLoc)
: Kind(FieldDesignator) {
Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
Field.DotLoc = DotLoc.getRawEncoding();
@@ -2147,7 +2419,7 @@ public:
}
/// @brief Initializes an array designator.
- Designator(unsigned Index, SourceLocation LBracketLoc,
+ Designator(unsigned Index, SourceLocation LBracketLoc,
SourceLocation RBracketLoc)
: Kind(ArrayDesignator) {
ArrayOrRange.Index = Index;
@@ -2157,7 +2429,7 @@ public:
}
/// @brief Initializes a GNU array-range designator.
- Designator(unsigned Index, SourceLocation LBracketLoc,
+ Designator(unsigned Index, SourceLocation LBracketLoc,
SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
: Kind(ArrayRangeDesignator) {
ArrayOrRange.Index = Index;
@@ -2227,7 +2499,7 @@ public:
}
};
- static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
+ static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
unsigned NumDesignators,
Expr **IndexExprs, unsigned NumIndexExprs,
SourceLocation EqualOrColonLoc,
@@ -2241,8 +2513,8 @@ public:
// Iterator access to the designators.
typedef Designator* designators_iterator;
designators_iterator designators_begin() { return Designators; }
- designators_iterator designators_end() {
- return Designators + NumDesignators;
+ designators_iterator designators_end() {
+ return Designators + NumDesignators;
}
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
@@ -2264,7 +2536,7 @@ public:
void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }
/// @brief Retrieve the initializer value.
- Expr *getInit() const {
+ Expr *getInit() const {
return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
}
@@ -2294,21 +2566,19 @@ public:
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
- void ExpandDesignator(unsigned Idx, const Designator *First,
+ void ExpandDesignator(unsigned Idx, const Designator *First,
const Designator *Last);
virtual SourceRange getSourceRange() const;
- virtual void Destroy(ASTContext &C);
-
static bool classof(const Stmt *T) {
- return T->getStmtClass() == DesignatedInitExprClass;
+ return T->getStmtClass() == DesignatedInitExprClass;
}
static bool classof(const DesignatedInitExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ virtual child_iterator child_end();
};
/// \brief Represents an implicitly-generated value initialization of
@@ -2319,16 +2589,16 @@ public:
/// initializations not explicitly specified by the user.
///
/// \see InitListExpr
-class ImplicitValueInitExpr : public Expr {
+class ImplicitValueInitExpr : public Expr {
public:
- explicit ImplicitValueInitExpr(QualType ty)
+ explicit ImplicitValueInitExpr(QualType ty)
: Expr(ImplicitValueInitExprClass, ty) { }
/// \brief Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
: Expr(ImplicitValueInitExprClass, Empty) { }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitValueInitExprClass;
}
static bool classof(const ImplicitValueInitExpr *) { return true; }
@@ -2337,13 +2607,60 @@ public:
return SourceRange();
}
- ImplicitValueInitExpr *Clone(ASTContext &C) const;
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+class ParenListExpr : public Expr {
+ Stmt **Exprs;
+ unsigned NumExprs;
+ SourceLocation LParenLoc, RParenLoc;
+
+protected:
+ virtual void DoDestroy(ASTContext& C);
+
+public:
+ ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
+ unsigned numexprs, SourceLocation rparenloc);
+
+ ~ParenListExpr() {}
+
+ /// \brief Build an empty paren list.
+ //explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
+
+ unsigned getNumExprs() const { return NumExprs; }
+
+ const Expr* getExpr(unsigned Init) const {
+ assert(Init < getNumExprs() && "Initializer access out of range!");
+ return cast_or_null<Expr>(Exprs[Init]);
+ }
+
+ Expr* getExpr(unsigned Init) {
+ assert(Init < getNumExprs() && "Initializer access out of range!");
+ return cast_or_null<Expr>(Exprs[Init]);
+ }
+
+ Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LParenLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenListExprClass;
+ }
+ static bool classof(const ParenListExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ virtual child_iterator child_end();
};
+
//===----------------------------------------------------------------------===//
// Clang Extensions
//===----------------------------------------------------------------------===//
@@ -2363,9 +2680,9 @@ class ExtVectorElementExpr : public Expr {
public:
ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
SourceLocation loc)
- : Expr(ExtVectorElementExprClass, ty),
+ : Expr(ExtVectorElementExprClass, ty),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
-
+
/// \brief Build an empty vector element expression.
explicit ExtVectorElementExpr(EmptyShell Empty)
: Expr(ExtVectorElementExprClass, Empty) { }
@@ -2382,28 +2699,28 @@ public:
/// getNumElements - Get the number of components being selected.
unsigned getNumElements() const;
-
+
/// containsDuplicateElements - Return true if any element access is
/// repeated.
bool containsDuplicateElements() const;
-
+
/// getEncodedElementAccess - Encode the elements accessed into an llvm
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), AccessorLoc);
}
-
+
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool isArrow() const;
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ExtVectorElementExprClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExtVectorElementExprClass;
}
static bool classof(const ExtVectorElementExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -2418,7 +2735,7 @@ protected:
bool HasBlockDeclRefExprs;
public:
BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs)
- : Expr(BlockExprClass, ty),
+ : Expr(BlockExprClass, ty),
TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {}
/// \brief Build an empty block expression.
@@ -2445,25 +2762,25 @@ public:
bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; }
void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockExprClass;
}
static bool classof(const BlockExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
/// BlockDeclRefExpr - A reference to a declared variable, function,
/// enum, etc.
class BlockDeclRefExpr : public Expr {
- ValueDecl *D;
+ ValueDecl *D;
SourceLocation Loc;
bool IsByRef : 1;
bool ConstQualAdded : 1;
public:
- BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
+ BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
bool constAdded = false) :
Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef),
ConstQualAdded(constAdded) {}
@@ -2472,7 +2789,7 @@ public:
// block.
explicit BlockDeclRefExpr(EmptyShell Empty)
: Expr(BlockDeclRefExprClass, Empty) { }
-
+
ValueDecl *getDecl() { return D; }
const ValueDecl *getDecl() const { return D; }
void setDecl(ValueDecl *VD) { D = VD; }
@@ -2481,18 +2798,18 @@ public:
void setLocation(SourceLocation L) { Loc = L; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
+
bool isByRef() const { return IsByRef; }
void setByRef(bool BR) { IsByRef = BR; }
-
+
bool isConstQualAdded() const { return ConstQualAdded; }
void setConstQualAdded(bool C) { ConstQualAdded = C; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == BlockDeclRefExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockDeclRefExprClass;
}
static bool classof(const BlockDeclRefExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 7d76a49d1267..3f66b1f40bfc 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -22,6 +22,7 @@ namespace clang {
class CXXConstructorDecl;
class CXXDestructorDecl;
+ class CXXMethodDecl;
class CXXTemporary;
//===--------------------------------------------------------------------===//
@@ -46,15 +47,19 @@ class CXXOperatorCallExpr : public CallExpr {
OverloadedOperatorKind Operator;
public:
- CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
- Expr **args, unsigned numargs, QualType t,
+ CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
+ Expr **args, unsigned numargs, QualType t,
SourceLocation operatorloc)
: CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc),
Operator(Op) {}
+ explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
+ CallExpr(C, CXXOperatorCallExprClass, Empty) { }
+
/// getOperator - Returns the kind of overloaded operator that this
/// expression refers to.
OverloadedOperatorKind getOperator() const { return Operator; }
+ void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; }
/// getOperatorLoc - Returns the location of the operator symbol in
/// the expression. When @c getOperator()==OO_Call, this is the
@@ -64,9 +69,9 @@ public:
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
virtual SourceRange getSourceRange() const;
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXOperatorCallExprClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXOperatorCallExprClass;
}
static bool classof(const CXXOperatorCallExpr *) { return true; }
};
@@ -90,7 +95,7 @@ public:
/// operation would return "x".
Expr *getImplicitObjectArgument();
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
}
static bool classof(const CXXMemberCallExpr *) { return true; }
@@ -108,9 +113,9 @@ private:
SourceLocation Loc; // the location of the casting op
protected:
- CXXNamedCastExpr(StmtClass SC, QualType ty, Expr *op, QualType writtenTy,
- SourceLocation l)
- : ExplicitCastExpr(SC, ty, op, writtenTy), Loc(l) {}
+ CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
+ QualType writtenTy, SourceLocation l)
+ : ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {}
public:
const char *getCastName() const;
@@ -123,7 +128,7 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
switch (T->getStmtClass()) {
case CXXNamedCastExprClass:
case CXXStaticCastExprClass:
@@ -139,32 +144,34 @@ public:
};
/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]).
-///
+///
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
public:
- CXXStaticCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, op, writtenTy, l) {}
+ CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
+ QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
static bool classof(const CXXStaticCastExpr *) { return true; }
};
/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
-/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
+/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
/// determine how to perform the type cast.
-///
+///
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
public:
- CXXDynamicCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, op, writtenTy, l) {}
+ CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
static bool classof(const CXXDynamicCastExpr *) { return true; }
@@ -173,16 +180,17 @@ public:
/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
/// [expr.reinterpret.cast]), which provides a differently-typed view
/// of a value but performs no actual work at run time.
-///
+///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
public:
- CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, op, writtenTy, l) {}
+ CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
+ QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op,
+ writtenTy, l) {}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
static bool classof(const CXXReinterpretCastExpr *) { return true; }
@@ -190,41 +198,39 @@ public:
/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
/// which can remove type qualifiers but does not change the underlying value.
-///
+///
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
public:
- CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {}
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
static bool classof(const CXXConstCastExpr *) { return true; }
};
/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
-///
+///
class CXXBoolLiteralExpr : public Expr {
bool Value;
SourceLocation Loc;
public:
- CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
+ CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {}
- CXXBoolLiteralExpr* Clone(ASTContext &C) const;
-
bool getValue() const { return Value; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXBoolLiteralExprClass;
}
static bool classof(const CXXBoolLiteralExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -237,8 +243,6 @@ public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {}
- CXXNullPtrLiteralExpr* Clone(ASTContext &C) const;
-
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
@@ -318,7 +322,7 @@ class CXXThisExpr : public Expr {
SourceLocation Loc;
public:
- CXXThisExpr(SourceLocation L, QualType Type)
+ CXXThisExpr(SourceLocation L, QualType Type)
: Expr(CXXThisExprClass, Type,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
@@ -327,7 +331,7 @@ public:
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXThisExprClass;
}
static bool classof(const CXXThisExpr *) { return true; }
@@ -379,14 +383,20 @@ public:
/// supply arguments for all of the parameters.
class CXXDefaultArgExpr : public Expr {
ParmVarDecl *Param;
+
+protected:
+ CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param)
+ : Expr(SC, param->hasUnparsedDefaultArg() ?
+ param->getType().getNonReferenceType()
+ : param->getDefaultArg()->getType()),
+ Param(param) { }
+
public:
// Param is the parameter whose default argument is used by this
// expression.
- explicit CXXDefaultArgExpr(ParmVarDecl *param)
- : Expr(CXXDefaultArgExprClass,
- param->hasUnparsedDefaultArg()? param->getType().getNonReferenceType()
- : param->getDefaultArg()->getType()),
- Param(param) { }
+ static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param) {
+ return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param);
+ }
// Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param; }
@@ -416,36 +426,39 @@ public:
class CXXTemporary {
/// Destructor - The destructor that needs to be called.
const CXXDestructorDecl *Destructor;
-
+
CXXTemporary(const CXXDestructorDecl *destructor)
: Destructor(destructor) { }
~CXXTemporary() { }
public:
- static CXXTemporary *Create(ASTContext &C,
+ static CXXTemporary *Create(ASTContext &C,
const CXXDestructorDecl *Destructor);
- void Destroy(ASTContext &C);
-
+
+ void Destroy(ASTContext &Ctx);
+
const CXXDestructorDecl *getDestructor() const { return Destructor; }
};
-/// CXXBindTemporaryExpr - Represents binding an expression to a temporary,
+/// CXXBindTemporaryExpr - Represents binding an expression to a temporary,
/// so its destructor can be called later.
class CXXBindTemporaryExpr : public Expr {
CXXTemporary *Temp;
-
+
Stmt *SubExpr;
- CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
+ CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
: Expr(CXXBindTemporaryExprClass,
subexpr->getType()), Temp(temp), SubExpr(subexpr) { }
- ~CXXBindTemporaryExpr() { }
+ ~CXXBindTemporaryExpr() { }
+
+protected:
+ virtual void DoDestroy(ASTContext &C);
public:
- static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp,
+ static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp,
Expr* SubExpr);
- void Destroy(ASTContext &C);
-
+
CXXTemporary *getTemporary() { return Temp; }
const CXXTemporary *getTemporary() const { return Temp; }
@@ -453,7 +466,9 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const { return SourceRange(); }
+ virtual SourceRange getSourceRange() const {
+ return SubExpr->getSourceRange();
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
@@ -471,32 +486,38 @@ class CXXConstructExpr : public Expr {
CXXConstructorDecl *Constructor;
bool Elidable;
-
+
Stmt **Args;
unsigned NumArgs;
-
protected:
- CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+ CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs);
- ~CXXConstructExpr() { }
+ ~CXXConstructExpr() { }
+
+ virtual void DoDestroy(ASTContext &C);
public:
+ /// \brief Construct an empty C++ construction expression that will store
+ /// \p numargs arguments.
+ CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs);
+
static CXXConstructExpr *Create(ASTContext &C, QualType T,
- CXXConstructorDecl *D, bool Elidable,
+ CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs);
-
- void Destroy(ASTContext &C);
-
- CXXConstructorDecl* getConstructor() const { return Constructor; }
+
+ CXXConstructorDecl* getConstructor() const { return Constructor; }
+ void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
+
/// \brief Whether this construction is elidable.
bool isElidable() const { return Elidable; }
-
+ void setElidable(bool E) { Elidable = E; }
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
-
+
arg_iterator arg_begin() { return Args; }
arg_iterator arg_end() { return Args + NumArgs; }
const_arg_iterator arg_begin() const { return Args; }
@@ -504,14 +525,36 @@ public:
unsigned getNumArgs() const { return NumArgs; }
- virtual SourceRange getSourceRange() const { return SourceRange(); }
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(Args[Arg]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(Args[Arg]);
+ }
+
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ Args[Arg] = ArgExpr;
+ }
+
+ virtual SourceRange getSourceRange() const {
+ // FIXME: Should we know where the parentheses are, if there are any?
+ if (NumArgs == 0)
+ return SourceRange();
+
+ return SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
T->getStmtClass() == CXXTemporaryObjectExprClass;
}
static bool classof(const CXXConstructExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -524,20 +567,21 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
- CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
- SourceLocation tyBeginLoc, Expr *castExpr,
- SourceLocation rParenLoc) :
- ExplicitCastExpr(CXXFunctionalCastExprClass, ty, castExpr, writtenTy),
- TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+ CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
+ SourceLocation tyBeginLoc, CastKind kind,
+ Expr *castExpr, SourceLocation rParenLoc)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
+ writtenTy),
+ TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXFunctionalCastExprClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFunctionalCastExprClass;
}
static bool classof(const CXXFunctionalCastExpr *) { return true; }
};
@@ -545,7 +589,7 @@ public:
/// @brief Represents a C++ functional cast expression that builds a
/// temporary object.
///
-/// This expression type represents a C++ "functional" cast
+/// This expression type represents a C++ "functional" cast
/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
/// constructor to build a temporary object. If N == 0 but no
/// constructor will be called (because the functional cast is
@@ -566,12 +610,12 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr {
SourceLocation RParenLoc;
public:
- CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
- QualType writtenTy, SourceLocation tyBeginLoc,
- Expr **Args,unsigned NumArgs,
+ CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
+ QualType writtenTy, SourceLocation tyBeginLoc,
+ Expr **Args,unsigned NumArgs,
SourceLocation rParenLoc);
- ~CXXTemporaryObjectExpr() { }
+ ~CXXTemporaryObjectExpr() { }
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -579,7 +623,7 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
static bool classof(const CXXTemporaryObjectExpr *) { return true; }
@@ -596,30 +640,28 @@ class CXXZeroInitValueExpr : public Expr {
public:
CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
- SourceLocation rParenLoc ) :
+ SourceLocation rParenLoc ) :
Expr(CXXZeroInitValueExprClass, ty, false, false),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
-
+
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
/// @brief Whether this initialization expression was
/// implicitly-generated.
- bool isImplicit() const {
- return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
+ bool isImplicit() const {
+ return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
}
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
-
- CXXZeroInitValueExpr* Clone(ASTContext &C) const;
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXZeroInitValueExprClass;
}
static bool classof(const CXXZeroInitValueExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -634,28 +676,26 @@ class CXXConditionDeclExpr : public DeclRefExpr {
public:
CXXConditionDeclExpr(SourceLocation startLoc,
SourceLocation eqLoc, VarDecl *var)
- : DeclRefExpr(CXXConditionDeclExprClass, var,
+ : DeclRefExpr(CXXConditionDeclExprClass, var,
var->getType().getNonReferenceType(), startLoc,
var->getType()->isDependentType(),
/*FIXME:integral constant?*/
var->getType()->isDependentType()) {}
- virtual void Destroy(ASTContext& Ctx);
-
SourceLocation getStartLoc() const { return getLocation(); }
-
+
VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
virtual SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
}
-
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConditionDeclExprClass;
}
static bool classof(const CXXConditionDeclExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -707,7 +747,7 @@ public:
QualType getAllocatedType() const {
assert(getType()->isPointerType());
- return getType()->getAsPointerType()->getPointeeType();
+ return getType()->getAs<PointerType>()->getPointeeType();
}
FunctionDecl *getOperatorNew() const { return OperatorNew; }
@@ -831,6 +871,108 @@ public:
virtual child_iterator child_end();
};
+/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
+///
+/// Example:
+///
+/// \code
+/// template<typename T>
+/// void destroy(T* ptr) {
+/// ptr->~T();
+/// }
+/// \endcode
+///
+/// When the template is parsed, the expression \c ptr->~T will be stored as
+/// a member reference expression. If it then instantiated with a scalar type
+/// as a template argument for T, the resulting expression will be a
+/// pseudo-destructor expression.
+class CXXPseudoDestructorExpr : public Expr {
+ /// \brief The base expression (that is being destroyed).
+ Stmt *Base;
+
+ /// \brief Whether the operator was an arrow ('->'); otherwise, it was a
+ /// period ('.').
+ bool IsArrow : 1;
+
+ /// \brief The location of the '.' or '->' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The nested-name-specifier that follows the operator, if present.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The source range that covers the nested-name-specifier, if
+ /// present.
+ SourceRange QualifierRange;
+
+ /// \brief The type being destroyed.
+ QualType DestroyedType;
+
+ /// \brief The location of the type after the '~'.
+ SourceLocation DestroyedTypeLoc;
+
+public:
+ CXXPseudoDestructorExpr(ASTContext &Context,
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ QualType DestroyedType,
+ SourceLocation DestroyedTypeLoc)
+ : Expr(CXXPseudoDestructorExprClass,
+ Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
+ false, 0)),
+ /*isTypeDependent=*/false,
+ /*isValueDependent=*/Base->isValueDependent()),
+ Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
+ OperatorLoc(OperatorLoc), Qualifier(Qualifier),
+ QualifierRange(QualifierRange), DestroyedType(DestroyedType),
+ DestroyedTypeLoc(DestroyedTypeLoc) { }
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ /// \brief Determines whether this member expression actually had
+ /// a C++ nested-name-specifier prior to the name of the member, e.g.,
+ /// x->Base::foo.
+ bool hasQualifier() const { return Qualifier != 0; }
+
+ /// \brief If the member name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the member name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Determine whether this pseudo-destructor expression was written
+ /// using an '->' (otherwise, it used a '.').
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '.' or '->' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Retrieve the type that is being destroyed.
+ QualType getDestroyedType() const { return DestroyedType; }
+
+ /// \brief Retrieve the location of the type being destroyed.
+ SourceLocation getDestroyedTypeLoc() const { return DestroyedTypeLoc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Base->getLocStart(), DestroyedTypeLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXPseudoDestructorExprClass;
+ }
+ static bool classof(const CXXPseudoDestructorExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
/// \brief Represents the name of a function that has not been
/// resolved to any declaration.
///
@@ -848,7 +990,7 @@ public:
/// }
/// @endcode
class UnresolvedFunctionNameExpr : public Expr {
- /// The name that was present in the source
+ /// The name that was present in the source
DeclarationName Name;
/// The location of this name in the source code
@@ -867,9 +1009,7 @@ public:
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
- UnresolvedFunctionNameExpr* Clone(ASTContext &C) const;
-
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedFunctionNameExprClass;
}
static bool classof(const UnresolvedFunctionNameExpr *) { return true; }
@@ -909,7 +1049,7 @@ public:
QualType getQueriedType() const { return QueriedType; }
- bool EvaluateTrait() const;
+ bool EvaluateTrait(ASTContext&) const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryTypeTraitExprClass;
@@ -934,9 +1074,9 @@ class QualifiedDeclRefExpr : public DeclRefExpr {
NestedNameSpecifier *NNS;
public:
- QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
+ QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
bool VD, SourceRange R, NestedNameSpecifier *NNS)
- : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
+ : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
QualifierRange(R), NNS(NNS) { }
/// \brief Retrieve the source range of the nested-name-specifier.
@@ -946,8 +1086,8 @@ public:
/// declaration.
NestedNameSpecifier *getQualifier() const { return NNS; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(QualifierRange.getBegin(), getLocation());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(QualifierRange.getBegin(), getLocation());
}
static bool classof(const Stmt *T) {
@@ -985,11 +1125,16 @@ class UnresolvedDeclRefExpr : public Expr {
/// declaration name.
NestedNameSpecifier *NNS;
+ /// \brief Whether this expr is an address of (&) operand.
+ bool IsAddressOfOperand;
+
public:
UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
- SourceRange R, NestedNameSpecifier *NNS)
- : Expr(UnresolvedDeclRefExprClass, T, true, true),
- Name(N), Loc(L), QualifierRange(R), NNS(NNS) { }
+ SourceRange R, NestedNameSpecifier *NNS,
+ bool IsAddressOfOperand)
+ : Expr(UnresolvedDeclRefExprClass, T, true, true),
+ Name(N), Loc(L), QualifierRange(R), NNS(NNS),
+ IsAddressOfOperand(IsAddressOfOperand) { }
/// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return Name; }
@@ -1004,8 +1149,11 @@ public:
/// declaration.
NestedNameSpecifier *getQualifier() const { return NNS; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(QualifierRange.getBegin(), getLocation());
+ /// \brief Retrieve whether this is an address of (&) operand.
+
+ bool isAddressOfOperand() const { return IsAddressOfOperand; }
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(QualifierRange.getBegin(), getLocation());
}
static bool classof(const Stmt *T) {
@@ -1017,40 +1165,42 @@ public:
virtual StmtIterator child_end();
};
-/// \brief An expression that refers to a C++ template-id, such as
-/// @c isa<FunctionDecl>.
+/// \brief An expression that refers to a C++ template-id, such as
+/// @c isa<FunctionDecl>.
class TemplateIdRefExpr : public Expr {
/// \brief If this template-id was qualified-id, e.g., @c std::sort<int>,
/// this nested name specifier contains the @c std::.
NestedNameSpecifier *Qualifier;
-
+
/// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>,
/// this covers the source code range of the @c std::.
SourceRange QualifierRange;
-
+
/// \brief The actual template to which this template-id refers.
TemplateName Template;
-
+
/// \brief The source location of the template name.
SourceLocation TemplateNameLoc;
/// \brief The source location of the left angle bracket ('<');
SourceLocation LAngleLoc;
-
+
/// \brief The source location of the right angle bracket ('>');
SourceLocation RAngleLoc;
-
+
/// \brief The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
-
+
TemplateIdRefExpr(QualType T,
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
+ SourceLocation LAngleLoc,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
-
+
+ virtual void DoDestroy(ASTContext &Context);
+
public:
static TemplateIdRefExpr *
Create(ASTContext &Context, QualType T,
@@ -1058,77 +1208,77 @@ public:
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
-
- void Destroy(ASTContext &Context);
-
+
/// \brief Retrieve the nested name specifier used to qualify the name of
/// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL
/// if this template-id was an unqualified-id.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
-
+
/// \brief Retrieve the source range describing the nested name specifier
/// used to qualified the name of this template-id, if the name was qualified.
SourceRange getQualifierRange() const { return QualifierRange; }
-
+
/// \brief Retrieve the name of the template referenced, e.g., "sort" in
/// @c std::sort<int>;
TemplateName getTemplateName() const { return Template; }
-
+
/// \brief Retrieve the location of the name of the template referenced, e.g.,
/// the location of "sort" in @c std::sort<int>.
SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; }
-
- /// \brief Retrieve the location of the left angle bracket following the
+
+ /// \brief Retrieve the location of the left angle bracket following the
/// template name ('<').
SourceLocation getLAngleLoc() const { return LAngleLoc; }
-
+
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
+ const TemplateArgument *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgument *>(this + 1);
}
-
+
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
-
- /// \brief Retrieve the location of the right angle bracket following the
+
+ /// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>').
SourceLocation getRAngleLoc() const { return RAngleLoc; }
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc,
RAngleLoc);
}
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == TemplateIdRefExprClass;
}
static bool classof(const TemplateIdRefExpr *) { return true; }
};
-
+
class CXXExprWithTemporaries : public Expr {
Stmt *SubExpr;
-
+
CXXTemporary **Temps;
unsigned NumTemps;
bool ShouldDestroyTemps;
-
- CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
+
+ CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps, bool ShouldDestroyTemps);
~CXXExprWithTemporaries();
-
+
+protected:
+ virtual void DoDestroy(ASTContext &C);
+
public:
static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps,
bool ShouldDestroyTemporaries);
- void Destroy(ASTContext &C);
-
+
unsigned getNumTemporaries() const { return NumTemps; }
CXXTemporary *getTemporary(unsigned i) {
assert(i < NumTemps && "Index out of range");
@@ -1138,16 +1288,18 @@ public:
assert(i < NumTemps && "Index out of range");
return Temps[i];
}
-
+
bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; }
-
+
void removeLastTemporary() { NumTemps--; }
-
+
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const { return SourceRange(); }
+ virtual SourceRange getSourceRange() const {
+ return SubExpr->getSourceRange();
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
@@ -1196,7 +1348,7 @@ class CXXUnresolvedConstructExpr : public Expr {
/// \brief The number of arguments used to construct the type.
unsigned NumArgs;
-
+
CXXUnresolvedConstructExpr(SourceLocation TyBegin,
QualType T,
SourceLocation LParenLoc,
@@ -1205,7 +1357,7 @@ class CXXUnresolvedConstructExpr : public Expr {
SourceLocation RParenLoc);
public:
- static CXXUnresolvedConstructExpr *Create(ASTContext &C,
+ static CXXUnresolvedConstructExpr *Create(ASTContext &C,
SourceLocation TyBegin,
QualType T,
SourceLocation LParenLoc,
@@ -1247,7 +1399,7 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedConstructExprClass;
}
static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
@@ -1257,37 +1409,108 @@ public:
virtual child_iterator child_end();
};
-/// \brief
+/// \brief Represents a C++ member access expression where the actual member
+/// referenced could not be resolved, e.g., because the base expression or the
+/// member name was dependent.
class CXXUnresolvedMemberExpr : public Expr {
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
Stmt *Base;
-
+
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
- bool IsArrow;
+ bool IsArrow : 1;
+
+ /// \brief Whether this member expression has explicitly-specified template
+ /// arguments.
+ bool HasExplicitTemplateArgumentList : 1;
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
+ /// \brief The nested-name-specifier that precedes the member name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The source range covering the nested name specifier.
+ SourceRange QualifierRange;
+
+ /// \brief In a qualified member access expression such as t->Base::f, this
+ /// member stores the resolves of name lookup in the context of the member
+ /// access expression, to be used at instantiation time.
+ ///
+ /// FIXME: This member, along with the Qualifier and QualifierRange, could
+ /// be stuck into a structure that is optionally allocated at the end of
+ /// the CXXUnresolvedMemberExpr, to save space in the common case.
+ NamedDecl *FirstQualifierFoundInScope;
+
/// \brief The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
- /// FIXME: could also be a template-id, and we might have a
- /// nested-name-specifier as well.
+ /// FIXME: could also be a template-id
DeclarationName Member;
/// \brief The location of the member name.
SourceLocation MemberLoc;
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ return const_cast<CXXUnresolvedMemberExpr *>(this)
+ ->getExplicitTemplateArgumentList();
+ }
+
+ CXXUnresolvedMemberExpr(ASTContext &C,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationName Member,
+ SourceLocation MemberLoc,
+ bool HasExplicitTemplateArgs,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc);
+
public:
- CXXUnresolvedMemberExpr(ASTContext &C,
- Expr *Base, bool IsArrow,
+ CXXUnresolvedMemberExpr(ASTContext &C,
+ Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc)
- : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
- Base(Base), IsArrow(IsArrow), OperatorLoc(OperatorLoc),
- Member(Member), MemberLoc(MemberLoc) { }
+ : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
+ Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false),
+ OperatorLoc(OperatorLoc),
+ Qualifier(Qualifier), QualifierRange(QualifierRange),
+ FirstQualifierFoundInScope(FirstQualifierFoundInScope),
+ Member(Member), MemberLoc(MemberLoc) { }
+
+ static CXXUnresolvedMemberExpr *
+ Create(ASTContext &C,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationName Member,
+ SourceLocation MemberLoc,
+ bool HasExplicitTemplateArgs,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc);
/// \brief Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
@@ -1303,6 +1526,29 @@ public:
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Retrieve the source range covering the nested-name-specifier
+ /// that qualifies the member name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the first part of the nested-name-specifier that was
+ /// found in the scope of the member access expression when the member access
+ /// was initially parsed.
+ ///
+ /// This function only returns a useful result when member access expression
+ /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
+ /// returned by this function describes what was found by unqualified name
+ /// lookup for the identifier "Base" within the scope of the member access
+ /// expression itself. At template instantiation time, this information is
+ /// combined with the results of name lookup into the type of the object
+ /// expression itself (the class type of x).
+ NamedDecl *getFirstQualifierFoundInScope() const {
+ return FirstQualifierFoundInScope;
+ }
+
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMember() const { return Member; }
@@ -1313,11 +1559,58 @@ public:
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgumentList() {
+ return HasExplicitTemplateArgumentList;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgument *getTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgumentList()->getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->RAngleLoc;
+ }
+
virtual SourceRange getSourceRange() const {
+ if (HasExplicitTemplateArgumentList)
+ return SourceRange(Base->getSourceRange().getBegin(),
+ getRAngleLoc());
+
return SourceRange(Base->getSourceRange().getBegin(),
MemberLoc);
}
- static bool classof(const Stmt *T) {
+
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedMemberExprClass;
}
static bool classof(const CXXUnresolvedMemberExpr *) { return true; }
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index e00833b5820e..0613f4c095f8 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -22,7 +22,7 @@ namespace clang {
class ASTContext;
class ObjCMethodDecl;
class ObjCPropertyDecl;
-
+
/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
class ObjCStringLiteral : public Expr {
@@ -34,8 +34,6 @@ public:
explicit ObjCStringLiteral(EmptyShell Empty)
: Expr(ObjCStringLiteralClass, Empty) {}
- ObjCStringLiteral* Clone(ASTContext &C) const;
-
StringLiteral *getString() { return cast<StringLiteral>(String); }
const StringLiteral *getString() const { return cast<StringLiteral>(String); }
void setString(StringLiteral *S) { String = S; }
@@ -43,20 +41,20 @@ public:
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
- virtual SourceRange getSourceRange() const {
+ virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, String->getLocEnd());
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCStringLiteralClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCStringLiteralClass;
}
- static bool classof(const ObjCStringLiteral *) { return true; }
-
+ static bool classof(const ObjCStringLiteral *) { return true; }
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
/// and behavior as StringLiteral except that the string initializer is obtained
/// from ASTContext with the encoding type as an argument.
@@ -64,32 +62,32 @@ class ObjCEncodeExpr : public Expr {
QualType EncType;
SourceLocation AtLoc, RParenLoc;
public:
- ObjCEncodeExpr(QualType T, QualType ET,
+ ObjCEncodeExpr(QualType T, QualType ET,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCEncodeExprClass, T, ET->isDependentType(),
+ : Expr(ObjCEncodeExprClass, T, ET->isDependentType(),
ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {}
-
+
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
-
+
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
+
QualType getEncodedType() const { return EncType; }
void setEncodedType(QualType T) { EncType = T; }
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCEncodeExprClass;
}
static bool classof(const ObjCEncodeExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -106,11 +104,9 @@ public:
explicit ObjCSelectorExpr(EmptyShell Empty)
: Expr(ObjCSelectorExprClass, Empty) {}
- ObjCSelectorExpr *Clone(ASTContext &C) const;
-
Selector getSelector() const { return SelName; }
void setSelector(Selector S) { SelName = S; }
-
+
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
@@ -119,26 +115,26 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
-
+
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return SelName.getNumArgs(); }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCSelectorExprClass;
}
static bool classof(const ObjCSelectorExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used
/// as: @protocol(foo), as in:
/// obj conformsToProtocol:@protocol(foo)]
/// The return type is "Protocol*".
-class ObjCProtocolExpr : public Expr {
- ObjCProtocolDecl *TheProtocol;
+class ObjCProtocolExpr : public Expr {
+ ObjCProtocolDecl *TheProtocol;
SourceLocation AtLoc, RParenLoc;
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
@@ -148,11 +144,9 @@ public:
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
- ObjCProtocolExpr *Clone(ASTContext &C) const;
-
ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
-
+
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
@@ -161,12 +155,12 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCProtocolExprClass;
}
static bool classof(const ObjCProtocolExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -179,44 +173,44 @@ class ObjCIvarRefExpr : public Expr {
Stmt *Base;
bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
-
+
public:
ObjCIvarRefExpr(ObjCIvarDecl *d,
- QualType t, SourceLocation l, Expr *base=0,
- bool arrow = false, bool freeIvar = false) :
+ QualType t, SourceLocation l, Expr *base=0,
+ bool arrow = false, bool freeIvar = false) :
Expr(ObjCIvarRefExprClass, t), D(d),
Loc(l), Base(base), IsArrow(arrow),
IsFreeIvar(freeIvar) {}
-
+
explicit ObjCIvarRefExpr(EmptyShell Empty)
: Expr(ObjCIvarRefExprClass, Empty) {}
ObjCIvarDecl *getDecl() { return D; }
const ObjCIvarDecl *getDecl() const { return D; }
void setDecl(ObjCIvarDecl *d) { D = d; }
-
+
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr * base) { Base = base; }
-
+
bool isArrow() const { return IsArrow; }
bool isFreeIvar() const { return IsFreeIvar; }
void setIsArrow(bool A) { IsArrow = A; }
void setIsFreeIvar(bool A) { IsFreeIvar = A; }
-
+
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const {
+ virtual SourceRange getSourceRange() const {
return isFreeIvar() ? SourceRange(Loc)
- : SourceRange(getBase()->getLocStart(), Loc);
+ : SourceRange(getBase()->getLocStart(), Loc);
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCIvarRefExprClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIvarRefExprClass;
}
static bool classof(const ObjCIvarRefExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -231,113 +225,129 @@ private:
SourceLocation IdLoc;
Stmt *Base;
public:
- ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) {
}
-
+
explicit ObjCPropertyRefExpr(EmptyShell Empty)
: Expr(ObjCPropertyRefExprClass, Empty) {}
ObjCPropertyDecl *getProperty() const { return AsProperty; }
void setProperty(ObjCPropertyDecl *D) { AsProperty = D; }
-
+
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr *base) { Base = base; }
-
+
SourceLocation getLocation() const { return IdLoc; }
void setLocation(SourceLocation L) { IdLoc = L; }
virtual SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), IdLoc);
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCPropertyRefExprClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCPropertyRefExprClass;
}
static bool classof(const ObjCPropertyRefExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-/// ObjCKVCRefExpr - A dot-syntax expression to access "implicit" properties
-/// (i.e. methods following the property naming convention). KVC stands for
-/// Key Value Encoding, a generic concept for accessing or setting a 'Key'
-/// value for an object.
-///
-class ObjCKVCRefExpr : public Expr {
+/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two
+/// methods; one to set a value to an 'ivar' (Setter) and the other to access
+/// an 'ivar' (Setter).
+/// An example for use of this AST is:
+/// @code
+/// @interface Test { }
+/// - (Test *)crash;
+/// - (void)setCrash: (Test*)value;
+/// @end
+/// void foo(Test *p1, Test *p2)
+/// {
+/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST
+/// }
+/// @endcode
+class ObjCImplicitSetterGetterRefExpr : public Expr {
+ /// Setter - Setter method user declared for setting its 'ivar' to a value
ObjCMethodDecl *Setter;
+ /// Getter - Getter method user declared for accessing 'ivar' it controls.
ObjCMethodDecl *Getter;
- SourceLocation Loc;
+ /// Location of the member in the dot syntax notation. This is location
+ /// of the getter method.
+ SourceLocation MemberLoc;
// FIXME: Swizzle these into a single pointer.
Stmt *Base;
- ObjCInterfaceDecl *ClassProp;
+ ObjCInterfaceDecl *InterfaceDecl;
+ /// Location of the receiver class in the dot syntax notation
+ /// used to call a class method setter/getter.
SourceLocation ClassLoc;
-
+
public:
- ObjCKVCRefExpr(ObjCMethodDecl *getter,
- QualType t,
+ ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
+ QualType t,
ObjCMethodDecl *setter,
SourceLocation l, Expr *base)
- : Expr(ObjCKVCRefExprClass, t), Setter(setter),
- Getter(getter), Loc(l), Base(base), ClassProp(0),
+ : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter),
+ Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0),
ClassLoc(SourceLocation()) {
}
- ObjCKVCRefExpr(ObjCMethodDecl *getter,
- QualType t,
+ ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
+ QualType t,
ObjCMethodDecl *setter,
SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
- : Expr(ObjCKVCRefExprClass, t), Setter(setter),
- Getter(getter), Loc(l), Base(0), ClassProp(C), ClassLoc(CL) {
+ : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter),
+ Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), ClassLoc(CL) {
}
- explicit ObjCKVCRefExpr(EmptyShell Empty) : Expr(ObjCKVCRefExprClass, Empty){}
+ explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty)
+ : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){}
ObjCMethodDecl *getGetterMethod() const { return Getter; }
ObjCMethodDecl *getSetterMethod() const { return Setter; }
- ObjCInterfaceDecl *getClassProp() const { return ClassProp; }
+ ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; }
void setGetterMethod(ObjCMethodDecl *D) { Getter = D; }
void setSetterMethod(ObjCMethodDecl *D) { Setter = D; }
- void setClassProp(ObjCInterfaceDecl *D) { ClassProp = D; }
-
+ void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; }
+
virtual SourceRange getSourceRange() const {
if (Base)
- return SourceRange(getBase()->getLocStart(), Loc);
- return SourceRange(ClassLoc, Loc);
+ return SourceRange(getBase()->getLocStart(), MemberLoc);
+ return SourceRange(ClassLoc, MemberLoc);
}
const Expr *getBase() const { return cast_or_null<Expr>(Base); }
Expr *getBase() { return cast_or_null<Expr>(Base); }
void setBase(Expr *base) { Base = base; }
-
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceLocation getLocation() const { return MemberLoc; }
+ void setLocation(SourceLocation L) { MemberLoc = L; }
SourceLocation getClassLoc() const { return ClassLoc; }
void setClassLoc(SourceLocation L) { ClassLoc = L; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCKVCRefExprClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass;
}
- static bool classof(const ObjCKVCRefExpr *) { return true; }
-
+ static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; }
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
class ObjCMessageExpr : public Expr {
// SubExprs - The receiver and arguments of the message expression.
Stmt **SubExprs;
-
+
// NumArgs - The number of arguments (not including the receiver) to the
// message expression.
unsigned NumArgs;
-
+
// A unigue name for this message.
Selector SelName;
-
- // A method prototype for this message (optional).
+
+ // A method prototype for this message (optional).
// FIXME: Since method decls contain the selector, and most messages have a
// prototype, consider devising a scheme for unifying SelName/MethodProto.
ObjCMethodDecl *MethodProto;
@@ -350,7 +360,7 @@ class ObjCMessageExpr : public Expr {
// Bit-swizzling flags.
enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }
-
+
public:
/// This constructor is used to represent class messages where the
/// ObjCInterfaceDecl* of the receiver is not known.
@@ -366,28 +376,28 @@ public:
QualType retType, ObjCMethodDecl *methDecl,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned NumArgs);
-
+
// constructor for instance messages.
ObjCMessageExpr(Expr *receiver, Selector selInfo,
QualType retType, ObjCMethodDecl *methDecl,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned NumArgs);
-
+
explicit ObjCMessageExpr(EmptyShell Empty)
: Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {}
-
+
~ObjCMessageExpr() {
delete [] SubExprs;
}
-
+
/// getReceiver - Returns the receiver of the message expression.
/// This can be NULL if the message is for class methods. For
/// class methods, use getClassName.
/// FIXME: need to handle/detect 'super' usage within a class method.
- Expr *getReceiver() {
+ Expr *getReceiver() {
uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
- }
+ }
const Expr *getReceiver() const {
return const_cast<ObjCMessageExpr*>(this)->getReceiver();
}
@@ -395,36 +405,36 @@ public:
void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; }
Selector getSelector() const { return SelName; }
void setSelector(Selector S) { SelName = S; }
-
+
const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
ObjCMethodDecl *getMethodDecl() { return MethodProto; }
void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; }
-
+
typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
-
+
/// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
/// and IdentifierInfo* of the invoked class. Both can be NULL if this
/// is an instance message, and the ObjCInterfaceDecl* can be NULL if none
- /// was available when this ObjCMessageExpr object was constructed.
- ClassInfo getClassInfo() const;
+ /// was available when this ObjCMessageExpr object was constructed.
+ ClassInfo getClassInfo() const;
void setClassInfo(const ClassInfo &C);
-
+
/// getClassName - For class methods, this returns the invoked class,
- /// and returns NULL otherwise. For instance methods, use getReceiver.
+ /// and returns NULL otherwise. For instance methods, use getReceiver.
IdentifierInfo *getClassName() const {
return getClassInfo().second;
}
-
+
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return NumArgs; }
- void setNumArgs(unsigned nArgs) {
- NumArgs = nArgs;
+ void setNumArgs(unsigned nArgs) {
+ NumArgs = nArgs;
// FIXME: should always allocate SubExprs via the ASTContext's
// allocator.
if (!SubExprs)
SubExprs = new Stmt* [NumArgs + 1];
}
-
+
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
@@ -439,13 +449,13 @@ public:
assert(Arg < NumArgs && "Arg access out of range!");
SubExprs[Arg+ARGS_START] = ArgExpr;
}
-
+
SourceLocation getLeftLoc() const { return LBracloc; }
SourceLocation getRightLoc() const { return RBracloc; }
void setLeftLoc(SourceLocation L) { LBracloc = L; }
void setRightLoc(SourceLocation L) { RBracloc = L; }
-
+
void setSourceRange(SourceRange R) {
LBracloc = R.getBegin();
RBracloc = R.getEnd();
@@ -458,14 +468,14 @@ public:
return T->getStmtClass() == ObjCMessageExprClass;
}
static bool classof(const ObjCMessageExpr *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
-
+
arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; }
const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
@@ -477,16 +487,16 @@ public:
class ObjCSuperExpr : public Expr {
SourceLocation Loc;
public:
- ObjCSuperExpr(SourceLocation L, QualType Type)
+ ObjCSuperExpr(SourceLocation L, QualType Type)
: Expr(ObjCSuperExprClass, Type), Loc(L) { }
explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {}
SourceLocation getLoc() const { return Loc; }
void setLoc(SourceLocation L) { Loc = L; }
-
+
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
- static bool classof(const Stmt *T) {
+ static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCSuperExprClass;
}
static bool classof(const ObjCSuperExpr *) { return true; }
@@ -496,6 +506,52 @@ public:
virtual child_iterator child_end();
};
+/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
+/// (similiar in spirit to MemberExpr).
+class ObjCIsaExpr : public Expr {
+ /// Base - the expression for the base object pointer.
+ Stmt *Base;
+
+ /// IsaMemberLoc - This is the location of the 'isa'.
+ SourceLocation IsaMemberLoc;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ bool IsArrow;
+public:
+ ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
+ : Expr(ObjCIsaExprClass, ty),
+ Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
+
+ /// \brief Build an empty expression.
+ explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// getMemberLoc - Return the location of the "member", in X->F, it is the
+ /// location of 'F'.
+ SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
+ void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
+ }
+
+ virtual SourceLocation getExprLoc() const { return IsaMemberLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIsaExprClass;
+ }
+ static bool classof(const ObjCIsaExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 6f862a55d4ba..0670d1a62094 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -33,7 +33,7 @@ struct VisibleDeclaration {
/// \brief The name of the declarations.
DeclarationName Name;
- /// \brief The ID numbers of all of the declarations with this name.
+ /// \brief The ID numbers of all of the declarations with this name.
///
/// These declarations have not necessarily been de-serialized.
llvm::SmallVector<unsigned, 4> Declarations;
@@ -65,7 +65,7 @@ public:
/// replaced with the sorted set of source ranges corresponding to
/// comments in the source code.
virtual void ReadComments(std::vector<SourceRange> &Comments) = 0;
-
+
/// \brief Resolve a type ID into a type, potentially building a new
/// type.
virtual QualType GetType(uint32_t ID) = 0;
@@ -151,7 +151,7 @@ public:
this->Ptr = reinterpret_cast<uint64_t>(Ptr);
return *this;
}
-
+
LazyOffsetPtr &operator=(uint64_t Offset) {
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
if (Offset == 0)
@@ -177,7 +177,7 @@ public:
/// \returns a pointer to the AST node.
T* get(ExternalASTSource *Source) const {
if (isOffset()) {
- assert(Source &&
+ assert(Source &&
"Cannot deserialize a lazy pointer without an AST source");
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
}
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index b304cc8e8a04..1594b090fea5 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
+#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -26,7 +27,7 @@ namespace clang {
class ASTContext;
class NamespaceDecl;
class IdentifierInfo;
-class PrintingPolicy;
+struct PrintingPolicy;
class Type;
class LangOptions;
@@ -80,8 +81,8 @@ private:
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
- NestedNameSpecifier(const NestedNameSpecifier &Other)
- : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
+ NestedNameSpecifier(const NestedNameSpecifier &Other)
+ : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
Specifier(Other.Specifier) {
}
@@ -89,7 +90,7 @@ private:
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
- static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
+ static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
const NestedNameSpecifier &Mockup);
public:
@@ -98,20 +99,28 @@ public:
/// The prefix must be dependent, since nested name specifiers
/// referencing an identifier are only permitted when the identifier
/// cannot be resolved.
- static NestedNameSpecifier *Create(ASTContext &Context,
- NestedNameSpecifier *Prefix,
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
IdentifierInfo *II);
/// \brief Builds a nested name specifier that names a namespace.
- static NestedNameSpecifier *Create(ASTContext &Context,
- NestedNameSpecifier *Prefix,
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
/// \brief Builds a nested name specifier that names a type.
- static NestedNameSpecifier *Create(ASTContext &Context,
- NestedNameSpecifier *Prefix,
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
bool Template, Type *T);
+ /// \brief Builds a specifier that consists of just an identifier.
+ ///
+ /// The nested-name-specifier is assumed to be dependent, but has no
+ /// prefix because the prefix is implied by something outside of the
+ /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
+ /// type.
+ static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II);
+
/// \brief Returns the nested name specifier representing the global
/// scope.
static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
@@ -126,10 +135,10 @@ public:
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
- SpecifierKind getKind() const {
+ SpecifierKind getKind() const {
if (Specifier == 0)
return Global;
- return (SpecifierKind)Prefix.getInt();
+ return (SpecifierKind)Prefix.getInt();
}
/// \brief Retrieve the identifier stored in this nested name
@@ -140,7 +149,7 @@ public:
return 0;
}
-
+
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
NamespaceDecl *getAsNamespace() const {
@@ -152,7 +161,7 @@ public:
/// \brief Retrieve the type stored in this nested name specifier.
Type *getAsType() const {
- if (Prefix.getInt() == TypeSpec ||
+ if (Prefix.getInt() == TypeSpec ||
Prefix.getInt() == TypeSpecWithTemplate)
return (Type *)Specifier;
@@ -179,6 +188,15 @@ public:
void dump(const LangOptions &LO);
};
+/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ NestedNameSpecifier *NNS) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
+ Diagnostic::ak_nestednamespec);
+ return DB;
+}
+
}
#endif
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index c669991ccc08..f826e1117b66 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -17,7 +17,7 @@
namespace clang {
class Stmt;
class Expr;
-
+
class ParentMap {
void* Impl;
public:
@@ -30,7 +30,7 @@ public:
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
}
-
+
const Stmt *getParentIgnoreParens(const Stmt *S) const {
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
@@ -38,13 +38,13 @@ public:
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}
-
+
bool isConsumedExpr(Expr *E) const;
-
+
bool isConsumedExpr(const Expr *E) const {
return isConsumedExpr(const_cast<Expr*>(E));
}
};
-
+
} // end clang namespace
#endif
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 6ad3a6bcc276..0635ec5dcd51 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -34,9 +34,10 @@ public:
/// declarations should be printed.
struct PrintingPolicy {
/// \brief Create a default printing policy for C.
- PrintingPolicy(const LangOptions &LO)
+ PrintingPolicy(const LangOptions &LO)
: Indentation(2), LangOpts(LO), SuppressSpecifiers(false),
- SuppressTag(false), SuppressTagKind(false), Dump(false) { }
+ SuppressTag(false), SuppressTagKind(false), SuppressScope(false),
+ Dump(false), ConstantArraySizeAsWritten(false) { }
/// \brief The number of spaces to use to indent each line.
unsigned Indentation : 8;
@@ -74,11 +75,32 @@ struct PrintingPolicy {
/// kind of tag, e.g., "struct", "union", "enum".
bool SuppressTagKind : 1;
+ /// \brief Suppresses printing of scope specifiers.
+ bool SuppressScope : 1;
+
/// \brief True when we are "dumping" rather than "pretty-printing",
/// where dumping involves printing the internal details of the AST
/// and pretty-printing involves printing something similar to
/// source code.
bool Dump : 1;
+
+ /// \brief Whether we should print the sizes of constant array expressions
+ /// as written in the sources.
+ ///
+ /// This flag is determines whether arrays types declared as
+ ///
+ /// \code
+ /// int a[4+10*10];
+ /// char a[] = "A string";
+ /// \endcode
+ ///
+ /// will be printed as written or as follows:
+ ///
+ /// \code
+ /// int a[104];
+ /// char a[9] = "A string";
+ /// \endcode
+ bool ConstantArraySizeAsWritten : 1;
};
} // end namespace clang
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index ab184563da23..7490b1d66b3e 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -18,83 +18,175 @@
namespace clang {
class ASTContext;
+ class FieldDecl;
class RecordDecl;
+ class CXXRecordDecl;
-/// ASTRecordLayout -
+/// ASTRecordLayout -
/// This class contains layout information for one RecordDecl,
/// which is a struct/union/class. The decl represented must be a definition,
-/// not a forward declaration.
-/// This class is also used to contain layout information for one
+/// not a forward declaration.
+/// This class is also used to contain layout information for one
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
- uint64_t Size; // Size of record in bits.
- uint64_t NextOffset; // Next available offset
+ /// Size - Size of record in bits.
+ uint64_t Size;
+
+ /// DataSize - Size of record in bits without tail padding.
+ uint64_t DataSize;
+
+ /// FieldOffsets - Array of field offsets in bits.
uint64_t *FieldOffsets;
- unsigned Alignment; // Alignment of record in bits.
- unsigned FieldCount; // Number of fields
+
+ // Alignment - Alignment of record in bits.
+ unsigned Alignment;
+
+ // FieldCount - Number of fields.
+ unsigned FieldCount;
+
+ struct CXXRecordLayoutInfo {
+ /// NonVirtualSize - The non-virtual size (in bits) of an object, which is
+ /// the size of the object without virtual bases.
+ uint64_t NonVirtualSize;
+
+ /// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
+ /// which is the alignment of the object without virtual bases.
+ uint64_t NonVirtualAlign;
+
+ /// PrimaryBase - The primary base for our vtable.
+ const CXXRecordDecl *PrimaryBase;
+ /// PrimaryBase - Wether or not the primary base was a virtual base.
+ bool PrimaryBaseWasVirtual;
+
+ /// BaseOffsets - Contains a map from base classes to their offset.
+ /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
+
+ /// VBaseOffsets - Contains a map from vbase classes to their offset.
+ /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
+ };
+
+ /// CXXInfo - If the record layout is for a C++ record, this will have
+ /// C++ specific information about the record.
+ CXXRecordLayoutInfo *CXXInfo;
+
friend class ASTContext;
+ friend class ASTRecordLayoutBuilder;
- ASTRecordLayout(uint64_t S = 0, unsigned A = 8)
- : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
- ~ASTRecordLayout() {
- delete [] FieldOffsets;
+ ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize,
+ const uint64_t *fieldoffsets, unsigned fieldcount)
+ : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
+ FieldCount(fieldcount), CXXInfo(0) {
+ if (FieldCount > 0) {
+ FieldOffsets = new uint64_t[FieldCount];
+ for (unsigned i = 0; i < FieldCount; ++i)
+ FieldOffsets[i] = fieldoffsets[i];
+ }
}
- /// Initialize record layout. N is the number of fields in this record.
- void InitializeLayout(unsigned N) {
- FieldCount = N;
- FieldOffsets = new uint64_t[N];
- }
+ // Constructor for C++ records.
+ ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize,
+ const uint64_t *fieldoffsets, unsigned fieldcount,
+ uint64_t nonvirtualsize, unsigned nonvirtualalign,
+ const CXXRecordDecl *PB, bool PBVirtual,
+ const std::pair<const CXXRecordDecl *, uint64_t> *bases,
+ unsigned numbases,
+ const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
+ unsigned numvbases)
+ : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
+ FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
+ if (FieldCount > 0) {
+ FieldOffsets = new uint64_t[FieldCount];
+ for (unsigned i = 0; i < FieldCount; ++i)
+ FieldOffsets[i] = fieldoffsets[i];
+ }
- /// Finalize record layout. Adjust record size based on the alignment.
- void FinalizeLayout(bool ForceNonEmpty = false) {
- // In C++, records cannot be of size 0.
- if (ForceNonEmpty && Size == 0)
- Size = 8;
- // Finally, round the size of the record up to the alignment of the
- // record itself.
- Size = (Size + (Alignment-1)) & ~(Alignment-1);
+ CXXInfo->PrimaryBase = PB;
+ CXXInfo->PrimaryBaseWasVirtual = PBVirtual;
+ CXXInfo->NonVirtualSize = nonvirtualsize;
+ CXXInfo->NonVirtualAlign = nonvirtualalign;
+ for (unsigned i = 0; i != numbases; ++i)
+ CXXInfo->BaseOffsets[bases[i].first] = bases[i].second;
+ for (unsigned i = 0; i != numvbases; ++i)
+ CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second;
}
- void SetFieldOffset(unsigned FieldNo, uint64_t Offset) {
- assert (FieldNo < FieldCount && "Invalid Field No");
- FieldOffsets[FieldNo] = Offset;
+ ~ASTRecordLayout() {
+ delete [] FieldOffsets;
+ delete CXXInfo;
}
- void SetAlignment(unsigned A) { Alignment = A; }
-
- /// LayoutField - Field layout. StructPacking is the specified
- /// packing alignment (maximum alignment) in bits to use for the
- /// structure, or 0 if no packing alignment is specified.
- void LayoutField(const FieldDecl *FD, unsigned FieldNo,
- bool IsUnion, unsigned StructPacking,
- ASTContext &Context);
-
ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
public:
-
+
/// getAlignment - Get the record alignment in bits.
unsigned getAlignment() const { return Alignment; }
/// getSize - Get the record size in bits.
uint64_t getSize() const { return Size; }
-
+
/// getFieldCount - Get the number of fields in the layout.
unsigned getFieldCount() const { return FieldCount; }
-
+
/// getFieldOffset - Get the offset of the given field index, in
/// bits.
uint64_t getFieldOffset(unsigned FieldNo) const {
assert (FieldNo < FieldCount && "Invalid Field No");
return FieldOffsets[FieldNo];
}
-
- /// getNextOffset - Get the next available (unused) offset in the
- /// structure, in bits.
- uint64_t getNextOffset() const {
- return NextOffset;
+
+ /// getDataSize() - Get the record data size, which is the record size
+ /// without tail padding, in bits.
+ uint64_t getDataSize() const {
+ return DataSize;
+ }
+
+ /// getNonVirtualSize - Get the non-virtual size (in bits) of an object,
+ /// which is the size of the object without virtual bases.
+ uint64_t getNonVirtualSize() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->NonVirtualSize;
+ }
+
+ /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object,
+ /// which is the alignment of the object without virtual bases.
+ unsigned getNonVirtualAlign() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->NonVirtualAlign;
+ }
+
+ /// getPrimaryBase - Get the primary base.
+ const CXXRecordDecl *getPrimaryBase() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->PrimaryBase;
+ }
+ /// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual.
+ bool getPrimaryBaseWasVirtual() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->PrimaryBaseWasVirtual;
+ }
+
+ /// getBaseClassOffset - Get the offset, in bits, for the given base class.
+ uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+
+ return CXXInfo->BaseOffsets[Base];
+ }
+
+ /// getVBaseClassOffset - Get the offset, in bits, for the given base class.
+ uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
+
+ return CXXInfo->VBaseOffsets[VBase];
}
};
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
new file mode 100644
index 000000000000..458af1f14423
--- /dev/null
+++ b/include/clang/AST/Redeclarable.h
@@ -0,0 +1,162 @@
+//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Redeclarable interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_REDECLARABLE_H
+#define LLVM_CLANG_AST_REDECLARABLE_H
+
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+
+/// \brief Provides common interface for the Decls that can be redeclared.
+template<typename decl_type>
+class Redeclarable {
+
+protected:
+ struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
+ DeclLink(decl_type *D, bool isLatest)
+ : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
+
+ typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type;
+
+ bool NextIsPrevious() const { return base_type::getInt() == false; }
+ bool NextIsLatest() const { return base_type::getInt() == true; }
+ decl_type *getNext() const { return base_type::getPointer(); }
+ };
+
+ struct PreviousDeclLink : public DeclLink {
+ PreviousDeclLink(decl_type *D) : DeclLink(D, false) { }
+ };
+
+ struct LatestDeclLink : public DeclLink {
+ LatestDeclLink(decl_type *D) : DeclLink(D, true) { }
+ };
+
+ /// \brief Points to the next redeclaration in the chain.
+ ///
+ /// If NextIsPrevious() is true, this is a link to the previous declaration
+ /// of this same Decl. If NextIsLatest() is true, this is the first
+ /// declaration and Link points to the latest declaration. For example:
+ ///
+ /// #1 int f(int x, int y = 1); // <pointer to #3, true>
+ /// #2 int f(int x = 0, int y); // <pointer to #1, false>
+ /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
+ ///
+ /// If there is only one declaration, it is <pointer to self, true>
+ DeclLink RedeclLink;
+
+public:
+ Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
+
+ /// \brief Return the previous declaration of this declaration or NULL if this
+ /// is the first declaration.
+ decl_type *getPreviousDeclaration() {
+ if (RedeclLink.NextIsPrevious())
+ return RedeclLink.getNext();
+ return 0;
+ }
+ const decl_type *getPreviousDeclaration() const {
+ return const_cast<decl_type *>(
+ static_cast<const decl_type*>(this))->getPreviousDeclaration();
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDeclaration() {
+ decl_type *D = static_cast<decl_type*>(this);
+ while (D->getPreviousDeclaration())
+ D = D->getPreviousDeclaration();
+ return D;
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDeclaration() const {
+ const decl_type *D = static_cast<const decl_type*>(this);
+ while (D->getPreviousDeclaration())
+ D = D->getPreviousDeclaration();
+ return D;
+ }
+
+ /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
+ /// first and only declaration.
+ void setPreviousDeclaration(decl_type *PrevDecl) {
+ decl_type *First;
+
+ if (PrevDecl) {
+ // Point to previous.
+ RedeclLink = PreviousDeclLink(PrevDecl);
+ First = PrevDecl->getFirstDeclaration();
+ assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ } else {
+ // Make this first.
+ First = static_cast<decl_type*>(this);
+ }
+
+ // First one will point to this one as latest.
+ First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
+ }
+
+ /// \brief Iterates through all the redeclarations of the same decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ decl_type *Current;
+ decl_type *Starter;
+
+ public:
+ typedef decl_type* value_type;
+ typedef decl_type* reference;
+ typedef decl_type* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ decl_type *Next = Current->RedeclLink.getNext();
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same decl.
+ /// It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<decl_type*>(
+ static_cast<const decl_type*>(this)));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 0a64dafd4e2c..411f215e912e 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -21,11 +21,14 @@
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/iterator.h"
#include "clang/AST/ASTContext.h"
#include <string>
using llvm::dyn_cast_or_null;
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
namespace clang {
class ASTContext;
class Expr;
@@ -36,21 +39,21 @@ namespace clang {
class SourceManager;
class StringLiteral;
class SwitchStmt;
-
+
//===----------------------------------------------------------------------===//
// ExprIterator - Iterators for iterating over Stmt* arrays that contain
// only Expr*. This is needed because AST nodes use Stmt* arrays to store
// references to children (to be compatible with StmtIterator).
//===----------------------------------------------------------------------===//
-
+
class Stmt;
class Expr;
-
+
class ExprIterator {
Stmt** I;
public:
ExprIterator(Stmt** i) : I(i) {}
- ExprIterator() : I(0) {}
+ ExprIterator() : I(0) {}
ExprIterator& operator++() { ++I; return *this; }
ExprIterator operator-(size_t i) { return I-i; }
ExprIterator operator+(size_t i) { return I+i; }
@@ -64,12 +67,12 @@ namespace clang {
bool operator>(const ExprIterator& R) const { return I > R.I; }
bool operator>=(const ExprIterator& R) const { return I >= R.I; }
};
-
+
class ConstExprIterator {
Stmt* const * I;
public:
ConstExprIterator(Stmt* const* i) : I(i) {}
- ConstExprIterator() : I(0) {}
+ ConstExprIterator() : I(0) {}
ConstExprIterator& operator++() { ++I; return *this; }
ConstExprIterator operator+(size_t i) { return I+i; }
ConstExprIterator operator-(size_t i) { return I-i; }
@@ -81,12 +84,12 @@ namespace clang {
bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
bool operator>(const ConstExprIterator& R) const { return I > R.I; }
bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
- };
-
+ };
+
//===----------------------------------------------------------------------===//
// AST classes for statements.
//===----------------------------------------------------------------------===//
-
+
/// Stmt - This represents one statement.
///
class Stmt {
@@ -101,7 +104,11 @@ public:
#include "clang/AST/StmtNodes.def"
};
private:
- const StmtClass sClass;
+ /// \brief The statement class.
+ const unsigned sClass : 8;
+
+ /// \brief The reference count for this statement.
+ unsigned RefCount : 24;
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
@@ -112,20 +119,20 @@ protected:
void operator delete(void* data) throw() {
assert(0 && "Stmts cannot be released with regular 'delete'.");
}
-
+
public:
// Only allow allocation of Stmts using the allocator in ASTContext
- // or by doing a placement new.
+ // or by doing a placement new.
void* operator new(size_t bytes, ASTContext& C,
unsigned alignment = 16) throw() {
return ::operator new(bytes, C, alignment);
}
-
+
void* operator new(size_t bytes, ASTContext* C,
unsigned alignment = 16) throw() {
return ::operator new(bytes, *C, alignment);
}
-
+
void* operator new(size_t bytes, void* mem) throw() {
return mem;
}
@@ -145,23 +152,48 @@ protected:
/// DestroyChildren - Invoked by destructors of subclasses of Stmt to
/// recursively release child AST nodes.
void DestroyChildren(ASTContext& Ctx);
-
+
/// \brief Construct an empty statement.
- explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) {
+ explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
+ /// \brief Virtual method that performs the actual destruction of
+ /// this statement.
+ ///
+ /// Subclasses should override this method (not Destroy()) to
+ /// provide class-specific destruction.
+ virtual void DoDestroy(ASTContext &Ctx);
+
public:
- Stmt(StmtClass SC) : sClass(SC) {
+ Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
virtual ~Stmt() {}
-
- virtual void Destroy(ASTContext &Ctx);
- StmtClass getStmtClass() const { return sClass; }
+ /// \brief Destroy the current statement and its children.
+ void Destroy(ASTContext &Ctx) {
+ assert(RefCount >= 1);
+ if (--RefCount == 0)
+ DoDestroy(Ctx);
+ }
+
+ /// \brief Increases the reference count for this statement.
+ ///
+ /// Invoke the Retain() operation when this statement or expression
+ /// is being shared by another owner.
+ Stmt *Retain() {
+ assert(RefCount >= 1);
+ ++RefCount;
+ return this;
+ }
+
+ StmtClass getStmtClass() const {
+ assert(RefCount >= 1 && "Referencing already-destroyed statement!");
+ return (StmtClass)sClass;
+ }
const char *getStmtClassName() const;
-
+
/// SourceLocation tokens are not useful in isolation - they are low level
/// value objects created/interpreted by SourceManager. We assume AST
/// clients will have a pointer to the respective SourceManager.
@@ -187,23 +219,23 @@ public:
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
/// back to its original source language syntax.
void dumpPretty(ASTContext& Context) const;
- void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper,
+ void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0) const {
printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
}
void printPretty(llvm::raw_ostream &OS, ASTContext &Context,
- PrinterHelper *Helper,
+ PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
-
+
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
/// works on systems with GraphViz (Mac OS X) or dot+gv installed.
void viewAST() const;
-
+
// Implement isa<T> support.
- static bool classof(const Stmt *) { return true; }
-
+ static bool classof(const Stmt *) { return true; }
+
/// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
/// contain implicit control-flow in the order their subexpressions
/// are evaluated. This predicate returns true if this statement has
@@ -216,46 +248,60 @@ public:
/// AST node. This permits easy iteration over all nodes in the AST.
typedef StmtIterator child_iterator;
typedef ConstStmtIterator const_child_iterator;
-
+
virtual child_iterator child_begin() = 0;
virtual child_iterator child_end() = 0;
-
+
const_child_iterator child_begin() const {
return const_child_iterator(const_cast<Stmt*>(this)->child_begin());
}
-
+
const_child_iterator child_end() const {
return const_child_iterator(const_cast<Stmt*>(this)->child_end());
}
+
+ /// \brief Produce a unique representation of the given statement.
+ ///
+ /// \brief ID once the profiling operation is complete, will contain
+ /// the unique representation of the given statement.
+ ///
+ /// \brief Context the AST context in which the statement resides
+ ///
+ /// \brief Canonical whether the profile should be based on the canonical
+ /// representation of this statement (e.g., where non-type template
+ /// parameters are identified by index/level rather than their
+ /// declaration pointers) or the exact representation of the statement as
+ /// written in the source.
+ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ bool Canonical);
};
/// DeclStmt - Adaptor class for mixing declarations with statements and
/// expressions. For example, CompoundStmt mixes statements, expressions
-/// and declarations (variables, types). Another example is ForStmt, where
+/// and declarations (variables, types). Another example is ForStmt, where
/// the first statement can be an expression or a declaration.
///
class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
+
public:
- DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
+ DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
StartLoc(startLoc), EndLoc(endLoc) {}
-
+
/// \brief Build an empty declaration statement.
explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
- virtual void Destroy(ASTContext& Ctx);
-
/// isSingleDecl - This method returns true if this DeclStmt refers
/// to a single Decl.
bool isSingleDecl() const {
return DG.isSingleDecl();
}
-
+
const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
- Decl *getSingleDecl() { return DG.getSingleDecl(); }
-
+ Decl *getSingleDecl() { return DG.getSingleDecl(); }
+
const DeclGroupRef getDeclGroup() const { return DG; }
DeclGroupRef getDeclGroup() { return DG; }
void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
@@ -268,19 +314,19 @@ public:
SourceRange getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == DeclStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclStmtClass;
}
static bool classof(const DeclStmt *) { return true; }
-
+
// Iterators over subexpressions.
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
+
typedef DeclGroupRef::iterator decl_iterator;
typedef DeclGroupRef::const_iterator const_decl_iterator;
-
+
decl_iterator decl_begin() { return DG.begin(); }
decl_iterator decl_end() { return DG.end(); }
const_decl_iterator decl_begin() const { return DG.begin(); }
@@ -297,18 +343,16 @@ public:
/// \brief Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
- NullStmt* Clone(ASTContext &C) const;
-
SourceLocation getSemiLoc() const { return SemiLoc; }
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == NullStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == NullStmtClass;
}
static bool classof(const NullStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -321,24 +365,24 @@ class CompoundStmt : public Stmt {
unsigned NumStmts;
SourceLocation LBracLoc, RBracLoc;
public:
- CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
+ CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
SourceLocation LB, SourceLocation RB)
: Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) {
if (NumStmts == 0) {
Body = 0;
return;
}
-
+
Body = new (C) Stmt*[NumStmts];
memcpy(Body, StmtStart, numStmts * sizeof(*Body));
- }
+ }
// \brief Build an empty compound statement.
explicit CompoundStmt(EmptyShell Empty)
: Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
-
+
bool body_empty() const { return NumStmts == 0; }
unsigned size() const { return NumStmts; }
@@ -366,25 +410,25 @@ public:
const_reverse_body_iterator body_rbegin() const {
return const_reverse_body_iterator(body_end());
}
-
+
const_reverse_body_iterator body_rend() const {
return const_reverse_body_iterator(body_begin());
}
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(LBracLoc, RBracLoc);
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LBracLoc, RBracLoc);
}
-
+
SourceLocation getLBracLoc() const { return LBracLoc; }
void setLBracLoc(SourceLocation L) { LBracLoc = L; }
SourceLocation getRBracLoc() const { return RBracLoc; }
void setRBracLoc(SourceLocation L) { RBracLoc = L; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CompoundStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundStmtClass;
}
static bool classof(const CompoundStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -398,7 +442,7 @@ protected:
SwitchCase *NextSwitchCase;
SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {}
-
+
public:
const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
@@ -409,19 +453,19 @@ public:
Stmt *getSubStmt() { return v_getSubStmt(); }
virtual SourceRange getSourceRange() const { return SourceRange(); }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CaseStmtClass ||
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass ||
T->getStmtClass() == DefaultStmtClass;
}
static bool classof(const SwitchCase *) { return true; }
protected:
- virtual Stmt* v_getSubStmt() = 0;
+ virtual Stmt* v_getSubStmt() = 0;
};
class CaseStmt : public SwitchCase {
enum { SUBSTMT, LHS, RHS, END_EXPR };
- Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
+ Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
// GNU "case 1 ... 4" extension
SourceLocation CaseLoc;
SourceLocation EllipsisLoc;
@@ -430,7 +474,7 @@ class CaseStmt : public SwitchCase {
virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
- SourceLocation ellipsisLoc, SourceLocation colonLoc)
+ SourceLocation ellipsisLoc, SourceLocation colonLoc)
: SwitchCase(CaseStmtClass) {
SubExprs[SUBSTMT] = 0;
SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
@@ -454,32 +498,32 @@ public:
Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
- const Expr *getLHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+ const Expr *getLHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[LHS]);
}
- const Expr *getRHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+ const Expr *getRHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[RHS]);
}
const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
-
-
+
+
virtual SourceRange getSourceRange() const {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
CS = CS2;
-
- return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd());
+
+ return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CaseStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass;
}
static bool classof(const CaseStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -491,7 +535,7 @@ class DefaultStmt : public SwitchCase {
SourceLocation ColonLoc;
virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
- DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
ColonLoc(CL) {}
@@ -507,14 +551,14 @@ public:
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(DefaultLoc, SubStmt->getLocEnd());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(DefaultLoc, SubStmt->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == DefaultStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DefaultStmtClass;
}
static bool classof(const DefaultStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -525,13 +569,13 @@ class LabelStmt : public Stmt {
Stmt *SubStmt;
SourceLocation IdentLoc;
public:
- LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
- : Stmt(LabelStmtClass), Label(label),
+ LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
+ : Stmt(LabelStmtClass), Label(label),
SubStmt(substmt), IdentLoc(IL) {}
// \brief Build an empty label statement.
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
-
+
SourceLocation getIdentLoc() const { return IdentLoc; }
IdentifierInfo *getID() const { return Label; }
void setID(IdentifierInfo *II) { Label = II; }
@@ -541,14 +585,14 @@ public:
void setIdentLoc(SourceLocation L) { IdentLoc = L; }
void setSubStmt(Stmt *SS) { SubStmt = SS; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(IdentLoc, SubStmt->getLocEnd());
- }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == LabelStmtClass;
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(IdentLoc, SubStmt->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == LabelStmtClass;
}
static bool classof(const LabelStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -563,8 +607,8 @@ class IfStmt : public Stmt {
SourceLocation IfLoc;
SourceLocation ElseLoc;
public:
- IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
- SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
+ IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
+ SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
: Stmt(IfStmtClass) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[THEN] = then;
@@ -572,14 +616,14 @@ public:
IfLoc = IL;
ElseLoc = EL;
}
-
+
/// \brief Build an empty if/then/else statement
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
const Stmt *getThen() const { return SubExprs[THEN]; }
- void setThen(Stmt *S) { SubExprs[THEN] = S; }
+ void setThen(Stmt *S) { SubExprs[THEN] = S; }
const Stmt *getElse() const { return SubExprs[ELSE]; }
void setElse(Stmt *S) { SubExprs[ELSE] = S; }
@@ -592,18 +636,18 @@ public:
SourceLocation getElseLoc() const { return ElseLoc; }
void setElseLoc(SourceLocation L) { ElseLoc = L; }
- virtual SourceRange getSourceRange() const {
+ virtual SourceRange getSourceRange() const {
if (SubExprs[ELSE])
return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
else
return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == IfStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IfStmtClass;
}
static bool classof(const IfStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -613,16 +657,20 @@ public:
///
class SwitchStmt : public Stmt {
enum { COND, BODY, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+ Stmt* SubExprs[END_EXPR];
// This points to a linked list of case and default statements.
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
+
+protected:
+ virtual void DoDestroy(ASTContext &Ctx);
+
public:
SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = NULL;
}
-
+
/// \brief Build a empty switch statement.
explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
@@ -635,28 +683,34 @@ public:
Stmt *getBody() { return SubExprs[BODY]; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SwitchCase *getSwitchCaseList() { return FirstCase; }
+
+ /// \brief Set the case list for this switch statement.
+ ///
+ /// The caller is responsible for incrementing the retain counts on
+ /// all of the SwitchCase statements in this list.
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
SourceLocation getSwitchLoc() const { return SwitchLoc; }
void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
- void setBody(Stmt *S, SourceLocation SL) {
- SubExprs[BODY] = S;
+ void setBody(Stmt *S, SourceLocation SL) {
+ SubExprs[BODY] = S;
SwitchLoc = SL;
- }
+ }
void addSwitchCase(SwitchCase *SC) {
assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
+ SC->Retain();
SC->setNextSwitchCase(FirstCase);
FirstCase = SC;
}
- virtual SourceRange getSourceRange() const {
- return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == SwitchStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SwitchStmtClass;
}
static bool classof(const SwitchStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -675,7 +729,7 @@ public:
SubExprs[BODY] = body;
WhileLoc = WL;
}
-
+
/// \brief Build an empty while statement.
explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
@@ -689,14 +743,14 @@ public:
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == WhileStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == WhileStmtClass;
}
static bool classof(const WhileStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -717,16 +771,16 @@ public:
: Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = body;
- }
+ }
/// \brief Build an empty do-while statement.
explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { }
-
+
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
Stmt *getBody() { return SubExprs[BODY]; }
- const Stmt *getBody() const { return SubExprs[BODY]; }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SourceLocation getDoLoc() const { return DoLoc; }
@@ -737,11 +791,11 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(DoLoc, RParenLoc);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(DoLoc, RParenLoc);
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == DoStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DoStmtClass;
}
static bool classof(const DoStmt *) { return true; }
@@ -763,7 +817,7 @@ class ForStmt : public Stmt {
public:
ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
- SourceLocation LP, SourceLocation RP)
+ SourceLocation LP, SourceLocation RP)
: Stmt(ForStmtClass) {
SubExprs[INIT] = Init;
SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
@@ -773,7 +827,7 @@ public:
LParenLoc = LP;
RParenLoc = RP;
}
-
+
/// \brief Build an empty for statement.
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
@@ -799,19 +853,19 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ForStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ForStmtClass;
}
static bool classof(const ForStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
/// GotoStmt - This represents a direct goto.
///
class GotoStmt : public Stmt {
@@ -819,9 +873,9 @@ class GotoStmt : public Stmt {
SourceLocation GotoLoc;
SourceLocation LabelLoc;
public:
- GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
+ GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
: Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
-
+
/// \brief Build an empty goto statement.
explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
@@ -833,14 +887,14 @@ public:
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(GotoLoc, LabelLoc);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(GotoLoc, LabelLoc);
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == GotoStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GotoStmtClass;
}
static bool classof(const GotoStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -853,20 +907,20 @@ class IndirectGotoStmt : public Stmt {
SourceLocation StarLoc;
Stmt *Target;
public:
- IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
+ IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
Expr *target)
: Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
Target((Stmt*)target) {}
/// \brief Build an empty indirect goto statement.
- explicit IndirectGotoStmt(EmptyShell Empty)
+ explicit IndirectGotoStmt(EmptyShell Empty)
: Stmt(IndirectGotoStmtClass, Empty) { }
-
+
void setGotoLoc(SourceLocation L) { GotoLoc = L; }
SourceLocation getGotoLoc() const { return GotoLoc; }
void setStarLoc(SourceLocation L) { StarLoc = L; }
SourceLocation getStarLoc() const { return StarLoc; }
-
+
Expr *getTarget();
const Expr *getTarget() const;
void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
@@ -874,12 +928,12 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(GotoLoc, Target->getLocEnd());
}
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == IndirectGotoStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IndirectGotoStmtClass;
}
static bool classof(const IndirectGotoStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -892,24 +946,22 @@ class ContinueStmt : public Stmt {
SourceLocation ContinueLoc;
public:
ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
-
+
/// \brief Build an empty continue statement.
explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
SourceLocation getContinueLoc() const { return ContinueLoc; }
void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(ContinueLoc);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ContinueLoc);
}
- ContinueStmt* Clone(ASTContext &C) const;
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ContinueStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ContinueStmtClass;
}
static bool classof(const ContinueStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -921,7 +973,7 @@ class BreakStmt : public Stmt {
SourceLocation BreakLoc;
public:
BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
-
+
/// \brief Build an empty break statement.
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
@@ -930,13 +982,11 @@ public:
virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
- BreakStmt* Clone(ASTContext &C) const;
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == BreakStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BreakStmtClass;
}
static bool classof(const BreakStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -956,7 +1006,7 @@ class ReturnStmt : public Stmt {
Stmt *RetExpr;
SourceLocation RetLoc;
public:
- ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass),
+ ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass),
RetExpr((Stmt*) E), RetLoc(RL) {}
/// \brief Build an empty return expression.
@@ -970,12 +1020,12 @@ public:
void setReturnLoc(SourceLocation L) { RetLoc = L; }
virtual SourceRange getSourceRange() const;
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ReturnStmtClass;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ReturnStmtClass;
}
static bool classof(const ReturnStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
@@ -989,18 +1039,18 @@ class AsmStmt : public Stmt {
bool IsSimple;
bool IsVolatile;
-
+
unsigned NumOutputs;
unsigned NumInputs;
-
+
llvm::SmallVector<std::string, 4> Names;
llvm::SmallVector<StringLiteral*, 4> Constraints;
llvm::SmallVector<Stmt*, 4> Exprs;
llvm::SmallVector<StringLiteral*, 4> Clobbers;
public:
- AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
- unsigned numoutputs, unsigned numinputs,
+ AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
+ unsigned numoutputs, unsigned numinputs,
std::string *names, StringLiteral **constraints,
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
StringLiteral **clobbers, SourceLocation rparenloc);
@@ -1043,10 +1093,10 @@ public:
: MyKind(Operand), Str(), OperandNo(OpNo) {
Str += Modifier;
}
-
+
bool isString() const { return MyKind == String; }
bool isOperand() const { return MyKind == Operand; }
-
+
const std::string &getString() const {
assert(isString());
return Str;
@@ -1056,7 +1106,7 @@ public:
assert(isOperand());
return OperandNo;
}
-
+
/// getModifier - Get the modifier for this operand, if present. This
/// returns '\0' if there was no modifier.
char getModifier() const {
@@ -1064,16 +1114,16 @@ public:
return Str[0];
}
};
-
+
/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
/// it into pieces. If the asm string is erroneous, emit errors and return
/// true, otherwise return false. This handles canonicalization and
/// translation of strings from GCC syntax to LLVM IR syntax, and handles
- //// flattening of named references like %[foo] to Operand AsmStringPiece's.
+ //// flattening of named references like %[foo] to Operand AsmStringPiece's.
unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
ASTContext &C, unsigned &DiagOffs) const;
-
-
+
+
//===--- Output operands ---===//
unsigned getNumOutputs() const { return NumOutputs; }
@@ -1086,72 +1136,72 @@ public:
/// output operand. All output constraints are known to be non-empty (either
/// '=' or '+').
std::string getOutputConstraint(unsigned i) const;
-
+
const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
return Constraints[i];
}
StringLiteral *getOutputConstraintLiteral(unsigned i) {
return Constraints[i];
}
-
-
+
+
Expr *getOutputExpr(unsigned i);
-
+
const Expr *getOutputExpr(unsigned i) const {
return const_cast<AsmStmt*>(this)->getOutputExpr(i);
}
-
+
/// isOutputPlusConstraint - Return true if the specified output constraint
/// is a "+" constraint (which is both an input and an output) or false if it
/// is an "=" constraint (just an output).
bool isOutputPlusConstraint(unsigned i) const {
return getOutputConstraint(i)[0] == '+';
}
-
+
/// getNumPlusOperands - Return the number of output operands that have a "+"
/// constraint.
unsigned getNumPlusOperands() const;
-
+
//===--- Input operands ---===//
-
- unsigned getNumInputs() const { return NumInputs; }
-
+
+ unsigned getNumInputs() const { return NumInputs; }
+
const std::string &getInputName(unsigned i) const {
return Names[i + NumOutputs];
}
-
+
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
std::string getInputConstraint(unsigned i) const;
-
+
const StringLiteral *getInputConstraintLiteral(unsigned i) const {
return Constraints[i + NumOutputs];
}
StringLiteral *getInputConstraintLiteral(unsigned i) {
return Constraints[i + NumOutputs];
}
-
-
+
+
Expr *getInputExpr(unsigned i);
-
+
const Expr *getInputExpr(unsigned i) const {
return const_cast<AsmStmt*>(this)->getInputExpr(i);
}
void setOutputsAndInputs(unsigned NumOutputs,
- unsigned NumInputs,
+ unsigned NumInputs,
const std::string *Names,
StringLiteral **Constraints,
Stmt **Exprs);
//===--- Other ---===//
-
+
/// getNamedOperand - Given a symbolic operand reference like %[foo],
/// translate this into a numeric value needed to reference the same operand.
/// This returns -1 if the operand name is invalid.
int getNamedOperand(const std::string &SymbolicName) const;
-
+
unsigned getNumClobbers() const { return Clobbers.size(); }
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
@@ -1161,62 +1211,62 @@ public:
virtual SourceRange getSourceRange() const {
return SourceRange(AsmLoc, RParenLoc);
}
-
+
static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;}
static bool classof(const AsmStmt *) { return true; }
-
+
// Input expr iterators.
-
+
typedef ExprIterator inputs_iterator;
typedef ConstExprIterator const_inputs_iterator;
-
+
inputs_iterator begin_inputs() {
return Exprs.data() + NumOutputs;
}
-
+
inputs_iterator end_inputs() {
return Exprs.data() + NumOutputs + NumInputs;
}
-
+
const_inputs_iterator begin_inputs() const {
return Exprs.data() + NumOutputs;
}
-
+
const_inputs_iterator end_inputs() const {
return Exprs.data() + NumOutputs + NumInputs;
}
-
+
// Output expr iterators.
-
+
typedef ExprIterator outputs_iterator;
typedef ConstExprIterator const_outputs_iterator;
-
+
outputs_iterator begin_outputs() {
return Exprs.data();
}
outputs_iterator end_outputs() {
return Exprs.data() + NumOutputs;
}
-
+
const_outputs_iterator begin_outputs() const {
return Exprs.data();
}
const_outputs_iterator end_outputs() const {
return Exprs.data() + NumOutputs;
}
-
+
// Input name iterator.
-
+
const std::string *begin_output_names() const {
return &Names[0];
}
-
+
const std::string *end_output_names() const {
return &Names[0] + NumOutputs;
}
-
- // Child iterators
-
+
+ // Child iterators
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 2338f1457a84..28fe348c4591 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -29,13 +29,14 @@ class CXXCatchStmt : public Stmt {
/// The handler block.
Stmt *HandlerBlock;
+protected:
+ virtual void DoDestroy(ASTContext& Ctx);
+
public:
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
HandlerBlock(handlerBlock) {}
- virtual void Destroy(ASTContext& Ctx);
-
virtual SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h
index 1bfac6a9587e..25d015287b75 100644
--- a/include/clang/AST/StmtGraphTraits.h
+++ b/include/clang/AST/StmtGraphTraits.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines a template specialization of llvm::GraphTraits to
+// This file defines a template specialization of llvm::GraphTraits to
// treat ASTs (Stmt*) as graphs
//
//===----------------------------------------------------------------------===//
@@ -20,7 +20,7 @@
#include "llvm/ADT/DepthFirstIterator.h"
namespace llvm {
-
+
//template <typename T> struct GraphTraits;
@@ -28,23 +28,23 @@ template <> struct GraphTraits<clang::Stmt*> {
typedef clang::Stmt NodeType;
typedef clang::Stmt::child_iterator ChildIteratorType;
typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
-
+
static NodeType* getEntryNode(clang::Stmt* S) { return S; }
-
+
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
-
+
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
-
+
static nodes_iterator nodes_begin(clang::Stmt* S) {
return df_begin(S);
}
-
+
static nodes_iterator nodes_end(clang::Stmt* S) {
return df_end(S);
}
@@ -55,29 +55,29 @@ template <> struct GraphTraits<const clang::Stmt*> {
typedef const clang::Stmt NodeType;
typedef clang::Stmt::const_child_iterator ChildIteratorType;
typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
-
+
static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
-
+
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
- else return ChildIteratorType();
+ else return ChildIteratorType();
}
-
+
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
-
+
static nodes_iterator nodes_begin(const clang::Stmt* S) {
return df_begin(S);
}
-
+
static nodes_iterator nodes_end(const clang::Stmt* S) {
return df_end(S);
}
};
-
+
} // end namespace llvm
#endif
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 35bd5ada0256..2d523fffce74 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -14,54 +14,54 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/ADT/iterator.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
+#include <iterator>
namespace clang {
class Stmt;
class Decl;
class VariableArrayType;
-
+
class StmtIteratorBase {
protected:
enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
Flags = 0x3 };
-
+
union { Stmt** stmt; Decl* decl; Decl** DGI; };
- uintptr_t RawVAPtr;
+ uintptr_t RawVAPtr;
Decl** DGE;
bool inDecl() const {
return (RawVAPtr & Flags) == DeclMode;
}
-
+
bool inDeclGroup() const {
return (RawVAPtr & Flags) == DeclGroupMode;
}
-
- bool inSizeOfTypeVA() const {
+
+ bool inSizeOfTypeVA() const {
return (RawVAPtr & Flags) == SizeOfTypeVAMode;
}
-
+
bool inStmt() const {
return (RawVAPtr & Flags) == 0;
}
-
+
VariableArrayType* getVAPtr() const {
return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
}
-
+
void setVAPtr(VariableArrayType* P) {
- assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
+ assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
-
+
void NextDecl(bool ImmediateAdvance = true);
bool HandleDecl(Decl* D);
void NextVA();
-
+
Stmt*& GetDeclExpr() const;
StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {}
@@ -70,22 +70,22 @@ protected:
StmtIteratorBase(Decl** dgi, Decl** dge);
StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {}
};
-
-
+
+
template <typename DERIVED, typename REFERENCE>
-class StmtIteratorImpl : public StmtIteratorBase,
+class StmtIteratorImpl : public StmtIteratorBase,
public std::iterator<std::forward_iterator_tag,
- REFERENCE, ptrdiff_t,
- REFERENCE, REFERENCE> {
+ REFERENCE, ptrdiff_t,
+ REFERENCE, REFERENCE> {
protected:
StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
public:
- StmtIteratorImpl() {}
+ StmtIteratorImpl() {}
StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {}
StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
-
+
DERIVED& operator++() {
if (inDecl() || inDeclGroup()) {
if (getVAPtr()) NextVA();
@@ -95,36 +95,36 @@ public:
NextVA();
else
++stmt;
-
+
return static_cast<DERIVED&>(*this);
}
-
+
DERIVED operator++(int) {
DERIVED tmp = static_cast<DERIVED&>(*this);
operator++();
return tmp;
}
-
+
bool operator==(const DERIVED& RHS) const {
return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr;
}
-
+
bool operator!=(const DERIVED& RHS) const {
return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr;
}
-
- REFERENCE operator*() const {
+
+ REFERENCE operator*() const {
return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
}
-
- REFERENCE operator->() const { return operator*(); }
+
+ REFERENCE operator->() const { return operator*(); }
};
struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
- StmtIterator(Decl** dgi, Decl** dge)
+ StmtIterator(Decl** dgi, Decl** dge)
: StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
@@ -133,10 +133,10 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
const Stmt*> {
- explicit ConstStmtIterator() :
+ explicit ConstStmtIterator() :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
-
- ConstStmtIterator(const StmtIterator& RHS) :
+
+ ConstStmtIterator(const StmtIterator& RHS) :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index a95a62731186..8d7e4b5fc0a3 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -25,6 +25,10 @@
# define EXPR(Type, Base) STMT(Type, Base)
#endif
+#ifndef ABSTRACT_EXPR
+# define ABSTRACT_EXPR(Type, Base) EXPR(Type, Base)
+#endif
+
// Normal Statements.
STMT(NullStmt , Stmt)
FIRST_STMT(NullStmt)
@@ -64,7 +68,7 @@ STMT(CXXTryStmt , Stmt)
LAST_STMT(CXXTryStmt)
// Expressions.
-EXPR(Expr , Stmt)
+ABSTRACT_EXPR(Expr , Stmt)
FIRST_EXPR(Expr)
EXPR(PredefinedExpr , Expr)
EXPR(DeclRefExpr , Expr)
@@ -91,6 +95,7 @@ EXPR(ExtVectorElementExpr , Expr)
EXPR(InitListExpr , Expr)
EXPR(DesignatedInitExpr , Expr)
EXPR(ImplicitValueInitExpr , Expr)
+EXPR(ParenListExpr , Expr)
EXPR(VAArgExpr , Expr)
// GNU Extensions.
@@ -119,6 +124,7 @@ EXPR(CXXZeroInitValueExpr , Expr)
EXPR(CXXConditionDeclExpr , DeclRefExpr)
EXPR(CXXNewExpr , Expr)
EXPR(CXXDeleteExpr , Expr)
+EXPR(CXXPseudoDestructorExpr, Expr)
EXPR(UnresolvedFunctionNameExpr , Expr)
EXPR(UnaryTypeTraitExpr , Expr)
EXPR(QualifiedDeclRefExpr , DeclRefExpr)
@@ -139,8 +145,9 @@ EXPR(ObjCSelectorExpr , Expr)
EXPR(ObjCProtocolExpr , Expr)
EXPR(ObjCIvarRefExpr , Expr)
EXPR(ObjCPropertyRefExpr , Expr)
-EXPR(ObjCKVCRefExpr , Expr)
+EXPR(ObjCImplicitSetterGetterRefExpr , Expr)
EXPR(ObjCSuperExpr , Expr)
+EXPR(ObjCIsaExpr , Expr)
// Clang Extensions.
EXPR(ShuffleVectorExpr , Expr)
@@ -149,8 +156,9 @@ EXPR(BlockDeclRefExpr , Expr)
LAST_EXPR(BlockDeclRefExpr)
-#undef STMT
+#undef ABSTRACT_EXPR
#undef EXPR
+#undef STMT
#undef FIRST_STMT
#undef LAST_STMT
#undef FIRST_EXPR
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index 8ae707174403..3fd8f1672deb 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -27,47 +27,47 @@ class ObjCForCollectionStmt : public Stmt {
SourceLocation ForLoc;
SourceLocation RParenLoc;
public:
- ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
+ ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
SourceLocation FCL, SourceLocation RPL);
- explicit ObjCForCollectionStmt(EmptyShell Empty) :
+ explicit ObjCForCollectionStmt(EmptyShell Empty) :
Stmt(ObjCForCollectionStmtClass, Empty) { }
-
+
Stmt *getElement() { return SubExprs[ELEM]; }
- Expr *getCollection() {
- return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+ Expr *getCollection() {
+ return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
}
Stmt *getBody() { return SubExprs[BODY]; }
-
+
const Stmt *getElement() const { return SubExprs[ELEM]; }
- const Expr *getCollection() const {
+ const Expr *getCollection() const {
return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
}
const Stmt *getBody() const { return SubExprs[BODY]; }
-
+
void setElement(Stmt *S) { SubExprs[ELEM] = S; }
- void setCollection(Expr *E) {
+ void setCollection(Expr *E) {
SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
}
void setBody(Stmt *S) { SubExprs[BODY] = S; }
-
+
SourceLocation getForLoc() const { return ForLoc; }
void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCForCollectionStmtClass;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCForCollectionStmtClass;
}
static bool classof(const ObjCForCollectionStmt *) { return true; }
-
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-};
-
+};
+
/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
class ObjCAtCatchStmt : public Stmt {
private:
@@ -78,95 +78,95 @@ private:
public:
ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
- ParmVarDecl *catchVarDecl,
+ ParmVarDecl *catchVarDecl,
Stmt *atCatchStmt, Stmt *atCatchList);
- explicit ObjCAtCatchStmt(EmptyShell Empty) :
+ explicit ObjCAtCatchStmt(EmptyShell Empty) :
Stmt(ObjCAtCatchStmtClass, Empty) { }
-
+
const Stmt *getCatchBody() const { return SubExprs[BODY]; }
Stmt *getCatchBody() { return SubExprs[BODY]; }
void setCatchBody(Stmt *S) { SubExprs[BODY] = S; }
-
+
const ObjCAtCatchStmt *getNextCatchStmt() const {
return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
}
- ObjCAtCatchStmt *getNextCatchStmt() {
+ ObjCAtCatchStmt *getNextCatchStmt() {
return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
}
void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; }
-
- const ParmVarDecl *getCatchParamDecl() const {
- return ExceptionDecl;
+
+ const ParmVarDecl *getCatchParamDecl() const {
+ return ExceptionDecl;
}
- ParmVarDecl *getCatchParamDecl() {
- return ExceptionDecl;
+ ParmVarDecl *getCatchParamDecl() {
+ return ExceptionDecl;
}
void setCatchParamDecl(ParmVarDecl *D) { ExceptionDecl = D; }
-
+
SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd());
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd());
}
bool hasEllipsis() const { return getCatchParamDecl() == 0; }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtCatchStmtClass;
}
static bool classof(const ObjCAtCatchStmt *) { return true; }
-
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
-/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
+
+/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
class ObjCAtFinallyStmt : public Stmt {
Stmt *AtFinallyStmt;
- SourceLocation AtFinallyLoc;
+ SourceLocation AtFinallyLoc;
public:
ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
- : Stmt(ObjCAtFinallyStmtClass),
+ : Stmt(ObjCAtFinallyStmtClass),
AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
- explicit ObjCAtFinallyStmt(EmptyShell Empty) :
+ explicit ObjCAtFinallyStmt(EmptyShell Empty) :
Stmt(ObjCAtFinallyStmtClass, Empty) { }
-
+
const Stmt *getFinallyBody() const { return AtFinallyStmt; }
Stmt *getFinallyBody() { return AtFinallyStmt; }
void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
}
-
+
SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtFinallyStmtClass;
}
static bool classof(const ObjCAtFinallyStmt *) { return true; }
-
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
-/// ObjCAtTryStmt - This represent objective-c's over-all
+
+/// ObjCAtTryStmt - This represent objective-c's over-all
/// @try ... @catch ... @finally statement.
class ObjCAtTryStmt : public Stmt {
private:
enum { TRY, CATCH, FINALLY, END_EXPR };
- Stmt* SubStmts[END_EXPR];
-
- SourceLocation AtTryLoc;
+ Stmt* SubStmts[END_EXPR];
+
+ SourceLocation AtTryLoc;
public:
- ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
- Stmt *atCatchStmt,
+ ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt *atCatchStmt,
Stmt *atFinallyStmt)
: Stmt(ObjCAtTryStmtClass) {
SubStmts[TRY] = atTryStmt;
@@ -174,41 +174,41 @@ public:
SubStmts[FINALLY] = atFinallyStmt;
AtTryLoc = atTryLoc;
}
- explicit ObjCAtTryStmt(EmptyShell Empty) :
+ explicit ObjCAtTryStmt(EmptyShell Empty) :
Stmt(ObjCAtTryStmtClass, Empty) { }
-
+
SourceLocation getAtTryLoc() const { return AtTryLoc; }
void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
-
+
const Stmt *getTryBody() const { return SubStmts[TRY]; }
Stmt *getTryBody() { return SubStmts[TRY]; }
void setTryBody(Stmt *S) { SubStmts[TRY] = S; }
-
- const ObjCAtCatchStmt *getCatchStmts() const {
- return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
+
+ const ObjCAtCatchStmt *getCatchStmts() const {
+ return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
}
- ObjCAtCatchStmt *getCatchStmts() {
- return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
+ ObjCAtCatchStmt *getCatchStmts() {
+ return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
}
void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; }
-
- const ObjCAtFinallyStmt *getFinallyStmt() const {
- return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
+
+ const ObjCAtFinallyStmt *getFinallyStmt() const {
+ return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
}
- ObjCAtFinallyStmt *getFinallyStmt() {
- return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
+ ObjCAtFinallyStmt *getFinallyStmt() {
+ return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
}
void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd());
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd());
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtTryStmtClass;
}
static bool classof(const ObjCAtTryStmt *) { return true; }
-
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
@@ -223,7 +223,7 @@ private:
enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
Stmt* SubStmts[END_EXPR];
SourceLocation AtSynchronizedLoc;
-
+
public:
ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
Stmt *synchBody)
@@ -232,41 +232,41 @@ public:
SubStmts[SYNC_BODY] = synchBody;
AtSynchronizedLoc = atSynchronizedLoc;
}
- explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
+ explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
-
+
SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
-
+
const CompoundStmt *getSynchBody() const {
return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
}
- CompoundStmt *getSynchBody() {
- return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
+ CompoundStmt *getSynchBody() {
+ return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
}
void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
-
- const Expr *getSynchExpr() const {
- return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+
+ const Expr *getSynchExpr() const {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
}
- Expr *getSynchExpr() {
- return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+ Expr *getSynchExpr() {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
}
void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
}
static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
-
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
-
+
/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
class ObjCAtThrowStmt : public Stmt {
Stmt *Throw;
@@ -276,28 +276,28 @@ public:
: Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
AtThrowLoc = atThrowLoc;
}
- explicit ObjCAtThrowStmt(EmptyShell Empty) :
+ explicit ObjCAtThrowStmt(EmptyShell Empty) :
Stmt(ObjCAtThrowStmtClass, Empty) { }
-
+
const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
void setThrowExpr(Stmt *S) { Throw = S; }
-
+
SourceLocation getThrowLoc() { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
-
+
virtual SourceRange getSourceRange() const {
if (Throw)
- return SourceRange(AtThrowLoc, Throw->getLocEnd());
- else
+ return SourceRange(AtThrowLoc, Throw->getLocEnd());
+ else
return SourceRange(AtThrowLoc);
}
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtThrowStmtClass;
}
static bool classof(const ObjCAtThrowStmt *) { return true; }
-
+
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 4f4066ab8602..3a525507dad3 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -20,17 +20,17 @@
#include "clang/AST/StmtObjC.h"
namespace clang {
-
+
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S))
-
+
/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
template<typename ImplClass, typename RetTy=void>
class StmtVisitor {
public:
RetTy Visit(Stmt *S) {
-
+
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
@@ -53,7 +53,7 @@ public:
case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator);
case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator);
case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator);
-
+
case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator);
case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator);
case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator);
@@ -101,7 +101,7 @@ public:
case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
}
}
-
+
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (S->getStmtClass()) {
default: assert(0 && "Unknown stmt kind!");
@@ -110,7 +110,7 @@ public:
#include "clang/AST/StmtNodes.def"
}
}
-
+
// If the implementation chooses not to implement a certain visit method, fall
// back on VisitExpr or whatever else is the superclass.
#define STMT(CLASS, PARENT) \
@@ -127,7 +127,7 @@ public:
BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem)
BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl)
BINOP_FALLBACK(Shr)
-
+
BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
@@ -148,7 +148,7 @@ public:
CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign)
CAO_FALLBACK(XorAssign)
#undef CAO_FALLBACK
-
+
// If the implementation doesn't implement unary operator methods, fall back
// on VisitUnaryOperator.
#define UNARYOP_FALLBACK(NAME) \
@@ -158,13 +158,13 @@ public:
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref)
-
+
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
#undef UNARYOP_FALLBACK
-
+
// Base case, ignore it. :)
RetTy VisitStmt(Stmt *Node) { return RetTy(); }
};
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index 511934c1dbf5..66ff34cf1e31 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -26,9 +26,11 @@ namespace clang {
class DependentTemplateName;
class IdentifierInfo;
class NestedNameSpecifier;
-class PrintingPolicy;
+struct PrintingPolicy;
class QualifiedTemplateName;
+class NamedDecl;
class TemplateDecl;
+class OverloadedFunctionDecl;
/// \brief Represents a C++ template name within the type system.
///
@@ -58,7 +60,8 @@ class TemplateDecl;
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
- typedef llvm::PointerUnion3<TemplateDecl *, QualifiedTemplateName *,
+ typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *,
+ QualifiedTemplateName *,
DependentTemplateName *> StorageType;
StorageType Storage;
@@ -70,17 +73,32 @@ class TemplateName {
public:
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
+ explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates)
+ : Storage(FunctionTemplates) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
+ /// \brief Determine whether this template name is NULL.
+ bool isNull() const { return Storage.isNull(); }
+
/// \brief Retrieve the the underlying template declaration that
/// this template name refers to, if known.
///
/// \returns The template declaration that this template name refers
/// to, if any. If the template name does not refer to a specific
- /// declaration because it is a dependent name, returns NULL.
+ /// declaration because it is a dependent name, or if it refers to a
+ /// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
+ /// \brief Retrieve the the underlying, overloaded function template
+ // declarations that this template name refers to, if known.
+ ///
+ /// \returns The set of overloaded function templates that this template
+ /// name refers to, if known. If the template name does not refer to a
+ /// specific set of function templates because it is a dependent name or
+ /// refers to a single template, returns NULL.
+ OverloadedFunctionDecl *getAsOverloadedFunctionDecl() const;
+
/// \brief Retrieve the underlying qualified template name
/// structure, if any.
QualifiedTemplateName *getAsQualifiedTemplateName() const {
@@ -119,8 +137,8 @@ public:
void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
/// \brief Build a template name from a void pointer.
- static TemplateName getFromVoidPointer(void *Ptr) {
- return TemplateName(Ptr);
+ static TemplateName getFromVoidPointer(void *Ptr) {
+ return TemplateName(Ptr);
}
};
@@ -145,15 +163,21 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// this name with DependentTemplateName).
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
- /// \brief The template declaration that this qualified name refers
- /// to.
- TemplateDecl *Template;
+ /// \brief The template declaration or set of overloaded function templates
+ /// that this qualified name refers to.
+ NamedDecl *Template;
friend class ASTContext;
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
TemplateDecl *Template)
- : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { }
+ : Qualifier(NNS, TemplateKeyword? 1 : 0),
+ Template(reinterpret_cast<NamedDecl *>(Template)) { }
+
+ QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
+ OverloadedFunctionDecl *Template)
+ : Qualifier(NNS, TemplateKeyword? 1 : 0),
+ Template(reinterpret_cast<NamedDecl *>(Template)) { }
public:
/// \brief Return the nested name specifier that qualifies this name.
@@ -163,16 +187,26 @@ public:
/// keyword.
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
+ /// \brief The template declaration or set of overloaded functions that
+ /// that qualified name refers to.
+ NamedDecl *getDecl() const { return Template; }
+
/// \brief The template declaration to which this qualified name
- /// refers.
- TemplateDecl *getTemplateDecl() const { return Template; }
+ /// refers, or NULL if this qualified name refers to a set of overloaded
+ /// function templates.
+ TemplateDecl *getTemplateDecl() const;
+
+ /// \brief The set of overloaded function tempaltes to which this qualified
+ /// name refers, or NULL if this qualified name refers to a single
+ /// template declaration.
+ OverloadedFunctionDecl *getOverloadedFunctionDecl() const;
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
+ Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl());
}
- static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- bool TemplateKeyword, TemplateDecl *Template) {
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ bool TemplateKeyword, NamedDecl *Template) {
ID.AddPointer(NNS);
ID.AddBoolean(TemplateKeyword);
ID.AddPointer(Template);
@@ -183,7 +217,7 @@ public:
/// resolved prior to template instantiation.
///
/// This kind of template name refers to a dependent template name,
-/// including its nested name specifier. For example,
+/// including its nested name specifier (if any). For example,
/// DependentTemplateName can refer to "MetaFun::template apply",
/// where "MetaFun::" is the nested name specifier and "apply" is the
/// template name referenced. The "template" keyword is implied.
@@ -205,11 +239,11 @@ class DependentTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;
- DependentTemplateName(NestedNameSpecifier *Qualifier,
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Name)
: Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { }
- DependentTemplateName(NestedNameSpecifier *Qualifier,
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Name,
TemplateName Canon)
: Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { }
@@ -226,7 +260,7 @@ public:
Profile(ID, getQualifier(), getName());
}
- static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
const IdentifierInfo *Name) {
ID.AddPointer(NNS);
ID.AddPointer(Name);
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index a00c0c4ff1c4..89776b91fe4a 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -19,6 +19,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/type_traits.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -29,7 +30,13 @@ using llvm::cast;
using llvm::cast_or_null;
using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
-namespace clang { class Type; }
+namespace clang {
+ enum {
+ TypeAlignmentInBits = 3,
+ TypeAlignment = 1 << TypeAlignmentInBits
+ };
+ class Type; class ExtQuals;
+}
namespace llvm {
template <typename T>
@@ -41,7 +48,16 @@ namespace llvm {
static inline ::clang::Type *getFromVoidPointer(void *P) {
return static_cast< ::clang::Type*>(P);
}
- enum { NumLowBitsAvailable = 3 };
+ enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
+ };
+ template<>
+ class PointerLikeTypeTraits< ::clang::ExtQuals*> {
+ public:
+ static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; }
+ static inline ::clang::ExtQuals *getFromVoidPointer(void *P) {
+ return static_cast< ::clang::ExtQuals*>(P);
+ }
+ enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
};
}
@@ -66,54 +82,359 @@ namespace clang {
class StmtIteratorBase;
class TemplateArgument;
class QualifiedNameType;
- class PrintingPolicy;
+ struct PrintingPolicy;
// Provide forward declarations for all of the *Type classes
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.def"
-/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
-/// their own: instead each reference to a type stores the qualifiers. This
-/// greatly reduces the number of nodes we need to allocate for types (for
-/// example we only need one for 'int', 'const int', 'volatile int',
-/// 'const volatile int', etc).
-///
-/// As an added efficiency bonus, instead of making this a pair, we just store
-/// the three bits we care about in the low bits of the pointer. To handle the
-/// packing/unpacking, we make QualType be a simple wrapper class that acts like
-/// a smart pointer.
-class QualType {
- llvm::PointerIntPair<Type*, 3> Value;
+/// Qualifiers - The collection of all-type qualifiers we support.
+/// Clang supports five independent qualifiers:
+/// * C99: const, volatile, and restrict
+/// * Embedded C (TR18037): address spaces
+/// * Objective C: the GC attributes (none, weak, or strong)
+class Qualifiers {
public:
- enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
Const = 0x1,
Restrict = 0x2,
Volatile = 0x4,
- CVRFlags = Const|Restrict|Volatile
+ CVRMask = Const | Volatile | Restrict
};
-
- enum GCAttrTypes {
+
+ enum GC {
GCNone = 0,
Weak,
Strong
};
-
+
+ enum {
+ /// The maximum supported address space number.
+ /// 24 bits should be enough for anyone.
+ MaxAddressSpace = 0xffffffu,
+
+ /// The width of the "fast" qualifier mask.
+ FastWidth = 2,
+
+ /// The fast qualifier mask.
+ FastMask = (1 << FastWidth) - 1
+ };
+
+ Qualifiers() : Mask(0) {}
+
+ static Qualifiers fromFastMask(unsigned Mask) {
+ Qualifiers Qs;
+ Qs.addFastQualifiers(Mask);
+ return Qs;
+ }
+
+ static Qualifiers fromCVRMask(unsigned CVR) {
+ Qualifiers Qs;
+ Qs.addCVRQualifiers(CVR);
+ return Qs;
+ }
+
+ // Deserialize qualifiers from an opaque representation.
+ static Qualifiers fromOpaqueValue(unsigned opaque) {
+ Qualifiers Qs;
+ Qs.Mask = opaque;
+ return Qs;
+ }
+
+ // Serialize these qualifiers into an opaque representation.
+ unsigned getAsOpaqueValue() const {
+ return Mask;
+ }
+
+ bool hasConst() const { return Mask & Const; }
+ void setConst(bool flag) {
+ Mask = (Mask & ~Const) | (flag ? Const : 0);
+ }
+ void removeConst() { Mask &= ~Const; }
+ void addConst() { Mask |= Const; }
+
+ bool hasVolatile() const { return Mask & Volatile; }
+ void setVolatile(bool flag) {
+ Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
+ }
+ void removeVolatile() { Mask &= ~Volatile; }
+ void addVolatile() { Mask |= Volatile; }
+
+ bool hasRestrict() const { return Mask & Restrict; }
+ void setRestrict(bool flag) {
+ Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
+ }
+ void removeRestrict() { Mask &= ~Restrict; }
+ void addRestrict() { Mask |= Restrict; }
+
+ bool hasCVRQualifiers() const { return getCVRQualifiers(); }
+ unsigned getCVRQualifiers() const { return Mask & CVRMask; }
+ void setCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask = (Mask & ~CVRMask) | mask;
+ }
+ void removeCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask &= ~mask;
+ }
+ void removeCVRQualifiers() {
+ removeCVRQualifiers(CVRMask);
+ }
+ void addCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask |= mask;
+ }
+
+ bool hasObjCGCAttr() const { return Mask & GCAttrMask; }
+ GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); }
+ void setObjCGCAttr(GC type) {
+ Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
+ }
+ void removeObjCGCAttr() { setObjCGCAttr(GCNone); }
+ void addObjCGCAttr(GC type) {
+ assert(type);
+ setObjCGCAttr(type);
+ }
+
+ bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
+ unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+ void setAddressSpace(unsigned space) {
+ assert(space <= MaxAddressSpace);
+ Mask = (Mask & ~AddressSpaceMask)
+ | (((uint32_t) space) << AddressSpaceShift);
+ }
+ void removeAddressSpace() { setAddressSpace(0); }
+ void addAddressSpace(unsigned space) {
+ assert(space);
+ setAddressSpace(space);
+ }
+
+ // Fast qualifiers are those that can be allocated directly
+ // on a QualType object.
+ bool hasFastQualifiers() const { return getFastQualifiers(); }
+ unsigned getFastQualifiers() const { return Mask & FastMask; }
+ void setFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask = (Mask & ~FastMask) | mask;
+ }
+ void removeFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask &= ~mask;
+ }
+ void removeFastQualifiers() {
+ removeFastQualifiers(FastMask);
+ }
+ void addFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask |= mask;
+ }
+
+ /// hasNonFastQualifiers - Return true if the set contains any
+ /// qualifiers which require an ExtQuals node to be allocated.
+ bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+ Qualifiers getNonFastQualifiers() const {
+ Qualifiers Quals = *this;
+ Quals.setFastQualifiers(0);
+ return Quals;
+ }
+
+ /// hasQualifiers - Return true if the set contains any qualifiers.
+ bool hasQualifiers() const { return Mask; }
+ bool empty() const { return !Mask; }
+
+ /// \brief Add the qualifiers from the given set to this set.
+ void addQualifiers(Qualifiers Q) {
+ // If the other set doesn't have any non-boolean qualifiers, just
+ // bit-or it in.
+ if (!(Q.Mask & ~CVRMask))
+ Mask |= Q.Mask;
+ else {
+ Mask |= (Q.Mask & CVRMask);
+ if (Q.hasAddressSpace())
+ addAddressSpace(Q.getAddressSpace());
+ if (Q.hasObjCGCAttr())
+ addObjCGCAttr(Q.getObjCGCAttr());
+ }
+ }
+
+ bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+ bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+
+ operator bool() const { return hasQualifiers(); }
+
+ Qualifiers &operator+=(Qualifiers R) {
+ addQualifiers(R);
+ return *this;
+ }
+
+ // Union two qualifier sets. If an enumerated qualifier appears
+ // in both sets, use the one from the right.
+ friend Qualifiers operator+(Qualifiers L, Qualifiers R) {
+ L += R;
+ return L;
+ }
+
+ std::string getAsString() const;
+ std::string getAsString(const PrintingPolicy &Policy) const {
+ std::string Buffer;
+ getAsStringInternal(Buffer, Policy);
+ return Buffer;
+ }
+ void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Mask);
+ }
+
+private:
+
+ // bits: |0 1 2|3 .. 4|5 .. 31|
+ // |C R V|GCAttr|AddrSpace|
+ uint32_t Mask;
+
+ static const uint32_t GCAttrMask = 0x18;
+ static const uint32_t GCAttrShift = 3;
+ static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
+ static const uint32_t AddressSpaceShift = 5;
+};
+
+
+/// ExtQuals - We can encode up to three bits in the low bits of a
+/// type pointer, but there are many more type qualifiers that we want
+/// to be able to apply to an arbitrary type. Therefore we have this
+/// struct, intended to be heap-allocated and used by QualType to
+/// store qualifiers.
+///
+/// The current design tags the 'const' and 'restrict' qualifiers in
+/// two low bits on the QualType pointer; a third bit records whether
+/// the pointer is an ExtQuals node. 'const' was chosen because it is
+/// orders of magnitude more common than the other two qualifiers, in
+/// both library and user code. It's relatively rare to see
+/// 'restrict' in user code, but many standard C headers are saturated
+/// with 'restrict' declarations, so that representing them efficiently
+/// is a critical goal of this representation.
+class ExtQuals : public llvm::FoldingSetNode {
+ // NOTE: changing the fast qualifiers should be straightforward as
+ // long as you don't make 'const' non-fast.
+ // 1. Qualifiers:
+ // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
+ // Fast qualifiers must occupy the low-order bits.
+ // b) Update Qualifiers::FastWidth and FastMask.
+ // 2. QualType:
+ // a) Update is{Volatile,Restrict}Qualified(), defined inline.
+ // b) Update remove{Volatile,Restrict}, defined near the end of
+ // this header.
+ // 3. ASTContext:
+ // a) Update get{Volatile,Restrict}Type.
+
+ /// Context - the context to which this set belongs. We save this
+ /// here so that QualifierCollector can use it to reapply extended
+ /// qualifiers to an arbitrary type without requiring a context to
+ /// be pushed through every single API dealing with qualifiers.
+ ASTContext& Context;
+
+ /// BaseType - the underlying type that this qualifies
+ const Type *BaseType;
+
+ /// Quals - the immutable set of qualifiers applied by this
+ /// node; always contains extended qualifiers.
+ Qualifiers Quals;
+
+public:
+ ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals)
+ : Context(Context), BaseType(Base), Quals(Quals)
+ {
+ assert(Quals.hasNonFastQualifiers()
+ && "ExtQuals created with no fast qualifiers");
+ assert(!Quals.hasFastQualifiers()
+ && "ExtQuals created with fast qualifiers");
+ }
+
+ Qualifiers getQualifiers() const { return Quals; }
+
+ bool hasVolatile() const { return Quals.hasVolatile(); }
+
+ bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
+ Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
+
+ bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+ const Type *getBaseType() const { return BaseType; }
+
+ ASTContext &getContext() const { return Context; }
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, getBaseType(), Quals);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const Type *BaseType,
+ Qualifiers Quals) {
+ assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
+ ID.AddPointer(BaseType);
+ Quals.Profile(ID);
+ }
+};
+
+
+/// QualType - For efficiency, we don't store CV-qualified types as nodes on
+/// their own: instead each reference to a type stores the qualifiers. This
+/// greatly reduces the number of nodes we need to allocate for types (for
+/// example we only need one for 'int', 'const int', 'volatile int',
+/// 'const volatile int', etc).
+///
+/// As an added efficiency bonus, instead of making this a pair, we
+/// just store the two bits we care about in the low bits of the
+/// pointer. To handle the packing/unpacking, we make QualType be a
+/// simple wrapper class that acts like a smart pointer. A third bit
+/// indicates whether there are extended qualifiers present, in which
+/// case the pointer points to a special structure.
+class QualType {
+ // Thankfully, these are efficiently composable.
+ llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
+ Qualifiers::FastWidth> Value;
+
+ bool hasExtQuals() const {
+ return Value.getPointer().is<const ExtQuals*>();
+ }
+
+ const ExtQuals *getExtQualsUnsafe() const {
+ return Value.getPointer().get<const ExtQuals*>();
+ }
+
+ const Type *getTypePtrUnsafe() const {
+ return Value.getPointer().get<const Type*>();
+ }
+
+ friend class QualifierCollector;
+public:
QualType() {}
-
+
QualType(const Type *Ptr, unsigned Quals)
- : Value(const_cast<Type*>(Ptr), Quals) {}
+ : Value(Ptr, Quals) {}
+ QualType(const ExtQuals *Ptr, unsigned Quals)
+ : Value(Ptr, Quals) {}
+
+ unsigned getFastQualifiers() const { return Value.getInt(); }
+ void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
+
+ /// Retrieves a pointer to the underlying (unqualified) type.
+ /// This should really return a const Type, but it's not worth
+ /// changing all the users right now.
+ Type *getTypePtr() const {
+ if (hasNonFastQualifiers())
+ return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
+ return const_cast<Type*>(getTypePtrUnsafe());
+ }
- unsigned getCVRQualifiers() const { return Value.getInt(); }
- void setCVRQualifiers(unsigned Quals) { Value.setInt(Quals); }
- Type *getTypePtr() const { return Value.getPointer(); }
-
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
static QualType getFromOpaquePtr(void *Ptr) {
QualType T;
T.Value.setFromOpaqueValue(Ptr);
return T;
}
-
+
Type &operator*() const {
return *getTypePtr();
}
@@ -121,65 +442,125 @@ public:
Type *operator->() const {
return getTypePtr();
}
-
+
/// isNull - Return true if this QualType doesn't point to a type yet.
bool isNull() const {
- return getTypePtr() == 0;
+ return Value.getPointer().isNull();
}
bool isConstQualified() const {
- return (getCVRQualifiers() & Const) ? true : false;
+ return (getFastQualifiers() & Qualifiers::Const);
+ }
+ bool isRestrictQualified() const {
+ return (getFastQualifiers() & Qualifiers::Restrict);
}
bool isVolatileQualified() const {
- return (getCVRQualifiers() & Volatile) ? true : false;
+ return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
}
- bool isRestrictQualified() const {
- return (getCVRQualifiers() & Restrict) ? true : false;
+
+ // Determines whether this type has any direct qualifiers.
+ bool hasQualifiers() const {
+ return getFastQualifiers() || hasNonFastQualifiers();
+ }
+
+ bool hasNonFastQualifiers() const {
+ return hasExtQuals();
+ }
+
+ // Retrieves the set of qualifiers belonging to this type.
+ Qualifiers getQualifiers() const {
+ Qualifiers Quals;
+ if (hasNonFastQualifiers())
+ Quals = getExtQualsUnsafe()->getQualifiers();
+ Quals.addFastQualifiers(getFastQualifiers());
+ return Quals;
}
- bool isConstant(ASTContext& Ctx) const;
-
- /// addConst/addVolatile/addRestrict - add the specified type qual to this
- /// QualType.
- void addConst() { Value.setInt(Value.getInt() | Const); }
- void addVolatile() { Value.setInt(Value.getInt() | Volatile); }
- void addRestrict() { Value.setInt(Value.getInt() | Restrict); }
+ // Retrieves the CVR qualifiers of this type.
+ unsigned getCVRQualifiers() const {
+ unsigned CVR = getFastQualifiers();
+ if (isVolatileQualified()) CVR |= Qualifiers::Volatile;
+ return CVR;
+ }
- void removeConst() { Value.setInt(Value.getInt() & ~Const); }
- void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); }
- void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); }
+ bool isConstant(ASTContext& Ctx) const {
+ return QualType::isConstant(*this, Ctx);
+ }
- QualType getQualifiedType(unsigned TQs) const {
- return QualType(getTypePtr(), TQs);
+ // Don't promise in the API that anything besides 'const' can be
+ // easily added.
+
+ /// addConst - add the specified type qualifier to this QualType.
+ void addConst() {
+ addFastQualifiers(Qualifiers::Const);
+ }
+ QualType withConst() const {
+ return withFastQualifiers(Qualifiers::Const);
}
- QualType getWithAdditionalQualifiers(unsigned TQs) const {
- return QualType(getTypePtr(), TQs|getCVRQualifiers());
+
+ void addFastQualifiers(unsigned TQs) {
+ assert(!(TQs & ~Qualifiers::FastMask)
+ && "non-fast qualifier bits set in mask!");
+ Value.setInt(Value.getInt() | TQs);
+ }
+
+ void removeConst();
+ void removeVolatile();
+ void removeRestrict();
+ void removeCVRQualifiers(unsigned Mask);
+
+ void removeFastQualifiers() { Value.setInt(0); }
+ void removeFastQualifiers(unsigned Mask) {
+ assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
+ Value.setInt(Value.getInt() & ~Mask);
+ }
+
+ // Creates a type with the given qualifiers in addition to any
+ // qualifiers already on this type.
+ QualType withFastQualifiers(unsigned TQs) const {
+ QualType T = *this;
+ T.addFastQualifiers(TQs);
+ return T;
+ }
+
+ // Creates a type with exactly the given fast qualifiers, removing
+ // any existing fast qualifiers.
+ QualType withExactFastQualifiers(unsigned TQs) const {
+ return withoutFastQualifiers().withFastQualifiers(TQs);
+ }
+
+ // Removes fast qualifiers, but leaves any extended qualifiers in place.
+ QualType withoutFastQualifiers() const {
+ QualType T = *this;
+ T.removeFastQualifiers();
+ return T;
}
- QualType withConst() const { return getWithAdditionalQualifiers(Const); }
- QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);}
- QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);}
-
- QualType getUnqualifiedType() const;
+ QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); }
+
bool isMoreQualifiedThan(QualType Other) const;
bool isAtLeastAsQualifiedAs(QualType Other) const;
QualType getNonReferenceType() const;
-
+
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
/// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
/// concrete.
- QualType getDesugaredType(bool ForDisplay = false) const;
+ ///
+ /// Qualifiers are left in place.
+ QualType getDesugaredType() const {
+ return QualType::getDesugaredType(*this);
+ }
/// operator==/!= - Indicate whether the specified types and qualifiers are
/// identical.
- bool operator==(const QualType &RHS) const {
- return Value == RHS.Value;
+ friend bool operator==(const QualType &LHS, const QualType &RHS) {
+ return LHS.Value == RHS.Value;
}
- bool operator!=(const QualType &RHS) const {
- return Value != RHS.Value;
+ friend bool operator!=(const QualType &LHS, const QualType &RHS) {
+ return LHS.Value != RHS.Value;
}
std::string getAsString() const;
@@ -190,31 +571,40 @@ public:
}
void getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const;
-
+
void dump(const char *s) const;
void dump() const;
-
+
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
}
-public:
-
/// getAddressSpace - Return the address space of this type.
inline unsigned getAddressSpace() const;
-
+
/// GCAttrTypesAttr - Returns gc attribute of this type.
- inline QualType::GCAttrTypes getObjCGCAttr() const;
+ inline Qualifiers::GC getObjCGCAttr() const;
/// isObjCGCWeak true when Type is objc's weak.
bool isObjCGCWeak() const {
- return getObjCGCAttr() == Weak;
+ return getObjCGCAttr() == Qualifiers::Weak;
}
/// isObjCGCStrong true when Type is objc's strong.
bool isObjCGCStrong() const {
- return getObjCGCAttr() == Strong;
+ return getObjCGCAttr() == Qualifiers::Strong;
}
+
+ /// getNoReturnAttr - Returns true if the type has the noreturn attribute,
+ /// false otherwise.
+ bool getNoReturnAttr() const;
+
+private:
+ // These methods are implemented in a separate translation unit;
+ // "static"-ize them to avoid creating temporary QualTypes in the
+ // caller.
+ static bool isConstant(QualType T, ASTContext& Ctx);
+ static QualType getDesugaredType(QualType T);
};
} // end clang.
@@ -230,7 +620,7 @@ template<> struct simplify_type<const ::clang::QualType> {
};
template<> struct simplify_type< ::clang::QualType>
: public simplify_type<const ::clang::QualType> {};
-
+
// Teach SmallPtrSet that QualType is "basically a pointer".
template<>
class PointerLikeTypeTraits<clang::QualType> {
@@ -241,9 +631,10 @@ public:
static inline clang::QualType getFromVoidPointer(void *P) {
return clang::QualType::getFromOpaquePtr(P);
}
- // CVR qualifiers go in low bits.
+ // Various qualifiers go in low bits.
enum { NumLowBitsAvailable = 0 };
};
+
} // end namespace llvm
namespace clang {
@@ -281,7 +672,10 @@ public:
#include "clang/AST/TypeNodes.def"
TagFirst = Record, TagLast = Enum
};
-
+
+protected:
+ enum { TypeClassBitSize = 6 };
+
private:
QualType CanonicalType;
@@ -291,7 +685,7 @@ private:
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
/// Note that this should stay at the end of the ivars for Type so that
/// subclasses can pack their bitfields into the same word.
- unsigned TC : 5;
+ unsigned TC : TypeClassBitSize;
Type(const Type&); // DO NOT IMPLEMENT.
void operator=(const Type&); // DO NOT IMPLEMENT.
@@ -304,15 +698,15 @@ protected:
virtual ~Type() {}
virtual void Destroy(ASTContext& C);
friend class ASTContext;
-
+
public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
-
+
bool isCanonical() const { return CanonicalType.getTypePtr() == this; }
- /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
+ /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.
-
+
/// \brief Determines whether the type describes an object in memory.
///
/// Note that this definition of object type corresponds to the C++
@@ -324,7 +718,7 @@ public:
/// isIncompleteType - Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
- /// routine will need to determine if the size is actually required.
+ /// routine will need to determine if the size is actually required.
bool isIncompleteType() const;
/// isIncompleteOrObjectType - Return true if this is an incomplete or object
@@ -339,13 +733,13 @@ public:
/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
/// types that have a non-constant expression. This does not include "[]".
bool isVariablyModifiedType() const;
-
+
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
/// isSpecificBuiltinType - Test for a particular builtin type.
bool isSpecificBuiltinType(unsigned K) const;
-
+
/// isIntegerType() does *not* include complex integers (a GCC extension).
/// isComplexIntegerType() can be used to test for complex integers.
bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
@@ -354,7 +748,7 @@ public:
bool isCharType() const;
bool isWideCharType() const;
bool isIntegralType() const;
-
+
/// Floating point categories.
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
/// isComplexType() does *not* include complex integers (a GCC extension).
@@ -368,13 +762,14 @@ public:
bool isDerivedType() const; // C99 6.2.5p20
bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
bool isAggregateType() const;
-
+
// Type Predicates: Check to see if this type is structurally the specified
// type, ignoring typedefs and qualifiers.
bool isFunctionType() const;
- bool isFunctionNoProtoType() const { return getAsFunctionNoProtoType() != 0; }
- bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; }
+ bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); }
+ bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
bool isPointerType() const;
+ bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
bool isBlockPointerType() const;
bool isVoidPointerType() const;
bool isReferenceType() const;
@@ -389,21 +784,27 @@ public:
bool isVariableArrayType() const;
bool isDependentSizedArrayType() const;
bool isRecordType() const;
- bool isClassType() const;
- bool isStructureType() const;
+ bool isClassType() const;
+ bool isStructureType() const;
bool isUnionType() const;
bool isComplexIntegerType() const; // GCC _Complex integer type.
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object.
+ // FIXME: change this to 'raw' interface type, so we can used 'interface' type
+ // for the common case.
bool isObjCInterfaceType() const; // NSString or NSString<foo>
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
+ bool isObjCQualifiedClassType() const; // Class<foo>
+ bool isObjCIdType() const; // id
+ bool isObjCClassType() const; // Class
+ bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
/// isDependentType - Whether this type is a dependent type, meaning
- /// that its definition somehow depends on a template parameter
+ /// that its definition somehow depends on a template parameter
/// (C++ [temp.dep.type]).
bool isDependentType() const { return Dependent; }
bool isOverloadableType() const;
@@ -416,41 +817,29 @@ public:
/// hasObjCPointerRepresentation - Whether this type can represent
/// an objective pointer type for the purpose of GC'ability
- bool hasObjCPointerRepresentation() const;
+ bool hasObjCPointerRepresentation() const;
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can.
- const BuiltinType *getAsBuiltinType() const;
- const FunctionType *getAsFunctionType() const;
- const FunctionNoProtoType *getAsFunctionNoProtoType() const;
- const FunctionProtoType *getAsFunctionProtoType() const;
- const PointerType *getAsPointerType() const;
- const BlockPointerType *getAsBlockPointerType() const;
- const ReferenceType *getAsReferenceType() const;
- const LValueReferenceType *getAsLValueReferenceType() const;
- const RValueReferenceType *getAsRValueReferenceType() const;
- const MemberPointerType *getAsMemberPointerType() const;
- const TagType *getAsTagType() const;
- const RecordType *getAsRecordType() const;
const RecordType *getAsStructureType() const;
/// NOTE: getAs*ArrayType are methods on ASTContext.
- const TypedefType *getAsTypedefType() const;
const RecordType *getAsUnionType() const;
- const EnumType *getAsEnumType() const;
- const VectorType *getAsVectorType() const; // GCC vector type.
- const ComplexType *getAsComplexType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
- const ExtVectorType *getAsExtVectorType() const; // Extended vector type.
- const ObjCObjectPointerType *getAsObjCObjectPointerType() const;
- const ObjCInterfaceType *getAsObjCInterfaceType() const;
- const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
+ // The following is a convenience method that returns an ObjCObjectPointerType
+ // for object declared using an interface.
+ const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
- const TemplateTypeParmType *getAsTemplateTypeParmType() const;
+ const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const;
+ const CXXRecordDecl *getCXXRecordDeclForPointerType() const;
+
+ // Member-template getAs<specific type>'. This scheme will eventually
+ // replace the specific getAsXXXX methods above.
+ //
+ // There are some specializations of this member template listed
+ // immediately following this class.
+ template <typename T> const T *getAs() const;
- const TemplateSpecializationType *
- getAsTemplateSpecializationType() const;
-
/// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
/// interface, return the interface type, otherwise return null.
const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
@@ -459,15 +848,16 @@ public:
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
const Type *getArrayElementTypeNoTypeQual() const;
-
- /// getDesugaredType - Return the specified type with any "sugar" removed from
- /// the type. This takes off typedefs, typeof's etc. If the outer level of
- /// the type is already concrete, it returns it unmodified. This is similar
- /// to getting the canonical type, but it doesn't remove *all* typedefs. For
- /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
- /// concrete.
- QualType getDesugaredType(bool ForDisplay = false) const;
-
+
+ /// getPointeeType - If this is a pointer, ObjC object pointer, or block
+ /// pointer, this returns the respective pointee.