summaryrefslogtreecommitdiff
path: root/include/clang/AST
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
commitbca07a4524feb4edec581062d631a13116320a24 (patch)
treea9243275843fbeaa590afc07ee888e006b8d54ea /include/clang/AST
parent998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff)
downloadsrc-test2-bca07a4524feb4edec581062d631a13116320a24.tar.gz
src-test2-bca07a4524feb4edec581062d631a13116320a24.zip
Notes
Diffstat (limited to 'include/clang/AST')
-rw-r--r--include/clang/AST/ASTConsumer.h8
-rw-r--r--include/clang/AST/ASTContext.h545
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/ASTImporter.h55
-rw-r--r--include/clang/AST/ASTMutationListener.h48
-rw-r--r--include/clang/AST/Attr.h31
-rw-r--r--include/clang/AST/CXXInheritance.h7
-rw-r--r--include/clang/AST/CanonicalType.h20
-rw-r--r--include/clang/AST/CharUnits.h50
-rw-r--r--include/clang/AST/Decl.h581
-rw-r--r--include/clang/AST/DeclBase.h75
-rw-r--r--include/clang/AST/DeclCXX.h563
-rw-r--r--include/clang/AST/DeclFriend.h29
-rw-r--r--include/clang/AST/DeclGroup.h2
-rw-r--r--include/clang/AST/DeclObjC.h119
-rw-r--r--include/clang/AST/DeclTemplate.h402
-rw-r--r--include/clang/AST/DeclarationName.h10
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h82
-rw-r--r--include/clang/AST/Expr.h1158
-rw-r--r--include/clang/AST/ExprCXX.h1061
-rw-r--r--include/clang/AST/ExprObjC.h386
-rw-r--r--include/clang/AST/ExternalASTSource.h48
-rw-r--r--include/clang/AST/FullExpr.h88
-rw-r--r--include/clang/AST/Mangle.h150
-rw-r--r--include/clang/AST/NestedNameSpecifier.h23
-rw-r--r--include/clang/AST/OperationKinds.h201
-rw-r--r--include/clang/AST/ParentMap.h10
-rw-r--r--include/clang/AST/PrettyPrinter.h4
-rw-r--r--include/clang/AST/RecordLayout.h169
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h325
-rw-r--r--include/clang/AST/Redeclarable.h20
-rw-r--r--include/clang/AST/Stmt.h371
-rw-r--r--include/clang/AST/StmtCXX.h12
-rw-r--r--include/clang/AST/StmtIterator.h96
-rw-r--r--include/clang/AST/StmtObjC.h39
-rw-r--r--include/clang/AST/TemplateBase.h283
-rw-r--r--include/clang/AST/TemplateName.h146
-rw-r--r--include/clang/AST/Type.h1915
-rw-r--r--include/clang/AST/TypeLoc.h347
-rw-r--r--include/clang/AST/TypeLocBuilder.h155
-rw-r--r--include/clang/AST/TypeNodes.def5
-rw-r--r--include/clang/AST/TypeVisitor.h9
42 files changed, 6396 insertions, 3254 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 84833c099f97..08ee4ef40de0 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -19,6 +19,7 @@ namespace clang {
class CXXRecordDecl;
class DeclGroupRef;
class HandleTagDeclDefinition;
+ class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
@@ -86,10 +87,13 @@ public:
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
+ /// \brief If the consumer is interested in entities getting modified after
+ /// their initial creation, it should return a pointer to
+ /// a GetASTMutationListener here.
+ virtual ASTMutationListener *GetASTMutationListener() { return 0; }
+
/// \brief If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
- ///
- /// The return type is void* because ASTDS lives in Frontend.
virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
/// PrintStats - If desired, print any statistics.
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index ae4ee946fe27..0e887133d01e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -45,6 +45,7 @@ namespace clang {
class Diagnostic;
class Expr;
class ExternalASTSource;
+ class ASTMutationListener;
class IdentifierTable;
class SelectorTable;
class SourceManager;
@@ -56,6 +57,7 @@ namespace clang {
class CXXRecordDecl;
class Decl;
class FieldDecl;
+ class MangleContext;
class ObjCIvarDecl;
class ObjCIvarRefExpr;
class ObjCPropertyDecl;
@@ -78,49 +80,61 @@ namespace clang {
class ASTContext {
ASTContext &this_() { return *this; }
- std::vector<Type*> Types;
- llvm::FoldingSet<ExtQuals> ExtQualNodes;
- llvm::FoldingSet<ComplexType> ComplexTypes;
- llvm::FoldingSet<PointerType> PointerTypes;
- llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
- llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
- llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
- llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
- llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
- llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
- std::vector<VariableArrayType*> VariableArrayTypes;
- 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<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
- llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
+ mutable std::vector<Type*> Types;
+ mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
+ mutable llvm::FoldingSet<ComplexType> ComplexTypes;
+ mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
+ mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
+ mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
+ mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
+ mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
+ mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
+ mutable std::vector<VariableArrayType*> VariableArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedExtVectorType>
+ DependentSizedExtVectorTypes;
+ mutable llvm::FoldingSet<VectorType> VectorTypes;
+ mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
+ mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+ mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
+ mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
+ mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmType>
+ SubstTemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmPackType>
+ SubstTemplateTypeParmPackTypes;
+ mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
TemplateSpecializationTypes;
- llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
- llvm::FoldingSet<DependentNameType> DependentNameTypes;
- llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&>
+ mutable llvm::FoldingSet<ParenType> ParenTypes;
+ mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
+ mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
+ mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
+ ASTContext&>
DependentTemplateSpecializationTypes;
- llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
- llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
-
- llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
- llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
-
+ llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
+ mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
+ mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<AttributedType> AttributedTypes;
+
+ mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
+ mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage>
+ SubstTemplateTemplateParmPacks;
+
/// \brief The set of nested name specifiers.
///
/// This set is managed by the NestedNameSpecifier class.
- llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
- NestedNameSpecifier *GlobalNestedNameSpecifier;
+ mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
+ mutable NestedNameSpecifier *GlobalNestedNameSpecifier;
friend class NestedNameSpecifier;
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
/// This is lazily created. This is intentionally not serialized.
- llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
- llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
+ mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>
+ ASTRecordLayouts;
+ mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>
+ ObjCLayouts;
/// KeyFunctions - A cache mapping from CXXRecordDecls to key functions.
llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
@@ -128,6 +142,9 @@ class ASTContext {
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+ /// \brief Mapping from __block VarDecls to their copy initialization expr.
+ llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
+
/// \brief Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
@@ -144,10 +161,11 @@ class ASTContext {
static void Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *Parm);
};
- llvm::FoldingSet<CanonicalTemplateTemplateParm> CanonTemplateTemplateParms;
+ mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
+ CanonTemplateTemplateParms;
- TemplateTemplateParmDecl *getCanonicalTemplateTemplateParmDecl(
- TemplateTemplateParmDecl *TTP);
+ TemplateTemplateParmDecl *
+ getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool IsInt128Installed;
@@ -171,11 +189,11 @@ class ASTContext {
QualType ObjCClassTypedefType;
QualType ObjCConstantStringType;
- RecordDecl *CFConstantStringTypeDecl;
+ mutable RecordDecl *CFConstantStringTypeDecl;
- RecordDecl *NSConstantStringTypeDecl;
+ mutable RecordDecl *NSConstantStringTypeDecl;
- RecordDecl *ObjCFastEnumerationStateTypeDecl;
+ mutable RecordDecl *ObjCFastEnumerationStateTypeDecl;
/// \brief The type for the C FILE type.
TypeDecl *FILEDecl;
@@ -187,10 +205,13 @@ class ASTContext {
TypeDecl *sigjmp_bufDecl;
/// \brief Type for the Block descriptor for Blocks CodeGen.
- RecordDecl *BlockDescriptorType;
+ mutable RecordDecl *BlockDescriptorType;
/// \brief Type for the Block descriptor for Blocks CodeGen.
- RecordDecl *BlockDescriptorExtendedType;
+ mutable RecordDecl *BlockDescriptorExtendedType;
+
+ /// \brief Declaration for the CUDA cudaConfigureCall function.
+ FunctionDecl *cudaConfigureCallDecl;
TypeSourceInfo NullTypeSourceInfo;
@@ -279,7 +300,7 @@ class ASTContext {
///
/// AST objects are never destructed; rather, all memory associated with the
/// AST objects will be released when the ASTContext itself is destroyed.
- llvm::BumpPtrAllocator BumpAlloc;
+ mutable llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
@@ -287,14 +308,17 @@ class ASTContext {
/// \brief The current C++ ABI.
llvm::OwningPtr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
-
+
+ friend class ASTDeclReader;
+
public:
const TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
- DeclarationNameTable DeclarationNames;
+ mutable DeclarationNameTable DeclarationNames;
llvm::OwningPtr<ExternalASTSource> ExternalSource;
+ ASTMutationListener *Listener;
clang::PrintingPolicy PrintingPolicy;
// Typedefs which may be provided defining the structure of Objective-C
@@ -305,10 +329,10 @@ public:
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
- void *Allocate(unsigned Size, unsigned Align = 8) {
+ void *Allocate(unsigned Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
- void Deallocate(void *Ptr) { }
+ void Deallocate(void *Ptr) const { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
@@ -316,6 +340,8 @@ public:
const LangOptions& getLangOptions() const { return LangOpts; }
+ Diagnostic &getDiagnostics() const;
+
FullSourceLoc getFullLoc(SourceLocation Loc) const {
return FullSourceLoc(Loc,SourceMgr);
}
@@ -388,7 +414,6 @@ public:
CanQualType VoidPtrTy, NullPtrTy;
CanQualType OverloadTy;
CanQualType DependentTy;
- CanQualType UndeducedAutoTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
@@ -409,6 +434,19 @@ public:
/// with this AST context, if any.
ExternalASTSource *getExternalSource() const { return ExternalSource.get(); }
+ /// \brief Attach an AST mutation listener to the AST context.
+ ///
+ /// The AST mutation listener provides the ability to track modifications to
+ /// the abstract syntax tree entities committed after they were initially
+ /// created.
+ void setASTMutationListener(ASTMutationListener *Listener) {
+ this->Listener = Listener;
+ }
+
+ /// \brief Retrieve a pointer to the AST mutation listener associated
+ /// with this AST context, if any.
+ ASTMutationListener *getASTMutationListener() const { return Listener; }
+
void PrintStats() const;
const std::vector<Type*>& getTypes() const { return Types; }
@@ -418,9 +456,9 @@ public:
private:
/// getExtQualType - Return a type with extended qualifiers.
- QualType getExtQualType(const Type *Base, Qualifiers Quals);
+ QualType getExtQualType(const Type *Base, Qualifiers Quals) const;
- QualType getTypeDeclTypeSlow(const TypeDecl *Decl);
+ QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
public:
/// getAddSpaceQualType - Return the uniqued reference to the type for an
@@ -428,24 +466,26 @@ public:
/// 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);
+ QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const;
/// 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, Qualifiers::GC gcAttr);
+ QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const;
/// 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) {
+ QualType getRestrictType(QualType T) const {
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);
+ QualType getVolatileType(QualType T) const {
+ return T.withFastQualifiers(Qualifiers::Volatile);
+ }
/// getConstType - Returns the uniqued reference to the type for a
/// 'const' qualified type. The resulting type has a union of the
@@ -453,44 +493,33 @@ public:
///
/// It can be reasonably expected that this will always be
/// equivalent to calling T.withConst().
- QualType getConstType(QualType T) { return T.withConst(); }
-
- /// getNoReturnType - Add or remove 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, bool AddNoReturn = true);
-
- /// getCallConvType - Adds the specified calling convention attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getCallConvType(QualType T, CallingConv CallConv);
+ QualType getConstType(QualType T) const { return T.withConst(); }
- /// getRegParmType - Sets the specified regparm attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getRegParmType(QualType T, unsigned RegParm);
+ /// adjustFunctionType - Change the ExtInfo on a function type.
+ const FunctionType *adjustFunctionType(const FunctionType *Fn,
+ FunctionType::ExtInfo EInfo);
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
- QualType getComplexType(QualType T);
- CanQualType getComplexType(CanQualType T) {
+ QualType getComplexType(QualType T) const;
+ CanQualType getComplexType(CanQualType T) const {
return CanQualType::CreateUnsafe(getComplexType((QualType) T));
}
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
- QualType getPointerType(QualType T);
- CanQualType getPointerType(CanQualType T) {
+ QualType getPointerType(QualType T) const;
+ CanQualType getPointerType(CanQualType T) const {
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
- QualType getBlockPointerType(QualType T);
+ QualType getBlockPointerType(QualType T) const;
/// This gets the struct used to keep track of the descriptor for pointer to
/// blocks.
- QualType getBlockDescriptorType();
+ QualType getBlockDescriptorType() const;
// Set the type for a Block descriptor type.
void setBlockDescriptorType(QualType T);
@@ -503,48 +532,56 @@ public:
/// This gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
- QualType getBlockDescriptorExtendedType();
+ QualType getBlockDescriptorExtendedType() const;
// Set the type for a Block descriptor extended type.
void setBlockDescriptorExtendedType(QualType T);
/// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been
/// built.
- QualType getRawBlockdescriptorExtendedType() {
+ QualType getRawBlockdescriptorExtendedType() const {
if (BlockDescriptorExtendedType)
return getTagDeclType(BlockDescriptorExtendedType);
return QualType();
}
+ void setcudaConfigureCallDecl(FunctionDecl *FD) {
+ cudaConfigureCallDecl = FD;
+ }
+ FunctionDecl *getcudaConfigureCallDecl() {
+ return cudaConfigureCallDecl;
+ }
+
/// This gets the struct used to keep track of pointer to blocks, complete
/// with captured variables.
QualType getBlockParmType(bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout);
+ llvm::SmallVectorImpl<const Expr *> &Layout) const;
/// This builds the struct used for __block variables.
- QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty);
+ QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
/// Returns true iff we need copy/dispose helpers for the given type.
- bool BlockRequiresCopying(QualType Ty);
+ bool BlockRequiresCopying(QualType Ty) const;
/// getLValueReferenceType - Return the uniqued reference to the type for an
/// lvalue reference to the specified type.
- QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true);
+ QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
+ const;
/// getRValueReferenceType - Return the uniqued reference to the type for an
/// rvalue reference to the specified type.
- QualType getRValueReferenceType(QualType T);
+ QualType getRValueReferenceType(QualType T) const;
/// getMemberPointerType - Return the uniqued reference to the type for a
/// member pointer to the specified type in the specified class. The class
/// is a Type because it could be a dependent name.
- QualType getMemberPointerType(QualType T, const Type *Cls);
+ QualType getMemberPointerType(QualType T, const Type *Cls) const;
/// getVariableArrayType - Returns a non-unique reference to the type for a
/// variable array of the specified element type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals,
- SourceRange Brackets);
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
/// getDependentSizedArrayType - Returns a non-unique reference to
/// the type for a dependently-sized array of the specified element
@@ -552,30 +589,34 @@ public:
/// comparable, at some point.
QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals,
- SourceRange Brackets);
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
/// getIncompleteArrayType - Returns a unique reference to the type for a
/// incomplete array of the specified element type.
QualType getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals);
+ unsigned IndexTypeQuals) const;
/// getConstantArrayType - Return the unique reference to the type for a
/// constant array of the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals);
+ unsigned IndexTypeQuals) const;
+
+ /// getVariableArrayDecayedType - Returns a vla type where known sizes
+ /// are replaced with [*].
+ QualType getVariableArrayDecayedType(QualType Ty) const;
/// 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,
- VectorType::AltiVecSpecific AltiVecSpec);
+ VectorType::VectorKind VecKind) const;
/// getExtVectorType - Return the unique reference to an extended vector type
/// of the specified element type and size. VectorType must be a built-in
/// type.
- QualType getExtVectorType(QualType VectorType, unsigned NumElts);
+ QualType getExtVectorType(QualType VectorType, unsigned NumElts) const;
/// getDependentSizedExtVectorType - Returns a non-unique reference to
/// the type for a dependently-sized vector of the specified element
@@ -583,30 +624,27 @@ public:
/// comparable, at some point.
QualType getDependentSizedExtVectorType(QualType VectorType,
Expr *SizeExpr,
- SourceLocation AttrLoc);
+ SourceLocation AttrLoc) const;
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy,
- const FunctionType::ExtInfo &Info);
+ const FunctionType::ExtInfo &Info) const;
- QualType getFunctionNoProtoType(QualType ResultTy) {
+ QualType getFunctionNoProtoType(QualType ResultTy) const {
return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo());
}
- /// getFunctionType - Return a normal function type with a typed argument
- /// list. isVariadic indicates whether the argument list includes '...'.
- QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
- unsigned NumArgs, bool isVariadic,
- unsigned TypeQuals, bool hasExceptionSpec,
- bool hasAnyExceptionSpec,
- unsigned NumExs, const QualType *ExArray,
- const FunctionType::ExtInfo &Info);
+ /// getFunctionType - Return a normal function type with a typed
+ /// argument list.
+ QualType getFunctionType(QualType ResultTy,
+ const QualType *Args, unsigned NumArgs,
+ const FunctionProtoType::ExtProtoInfo &EPI) const;
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
QualType getTypeDeclType(const TypeDecl *Decl,
- const TypeDecl *PrevDecl = 0) {
+ const TypeDecl *PrevDecl = 0) const {
assert(Decl && "Passed null for Decl param");
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
@@ -621,77 +659,93 @@ public:
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
- QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType());
+ QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType())
+ const;
+
+ QualType getRecordType(const RecordDecl *Decl) const;
- QualType getRecordType(const RecordDecl *Decl);
+ QualType getEnumType(const EnumDecl *Decl) const;
- QualType getEnumType(const EnumDecl *Decl);
+ QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
- QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
+ QualType getAttributedType(AttributedType::Kind attrKind,
+ QualType modifiedType,
+ QualType equivalentType);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
- QualType Replacement);
+ QualType Replacement) const;
+ QualType getSubstTemplateTypeParmPackType(
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
- IdentifierInfo *Name = 0);
+ IdentifierInfo *Name = 0) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
QualType getCanonicalTemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
- unsigned NumArgs);
+ unsigned NumArgs) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgumentListInfo &Args,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
TypeSourceInfo *
getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
const TemplateArgumentListInfo &Args,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
+
+ QualType getParenType(QualType NamedType) const;
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
- QualType NamedType);
+ QualType NamedType) const;
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
- const TemplateArgumentListInfo &Args);
+ const TemplateArgumentListInfo &Args) const;
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
unsigned NumArgs,
- const TemplateArgument *Args);
+ const TemplateArgument *Args) const;
+
+ QualType getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions);
- QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const;
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols);
+ unsigned NumProtocols) const;
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type
/// for the given ObjCObjectType.
- QualType getObjCObjectPointerType(QualType OIT);
+ QualType getObjCObjectPointerType(QualType OIT) const;
/// getTypeOfType - GCC extension.
- QualType getTypeOfExprType(Expr *e);
- QualType getTypeOfType(QualType t);
+ QualType getTypeOfExprType(Expr *e) const;
+ QualType getTypeOfType(QualType t) const;
/// getDecltypeType - C++0x decltype.
- QualType getDecltypeType(Expr *e);
+ QualType getDecltypeType(Expr *e) const;
+
+ /// getAutoType - C++0x deduced auto type.
+ QualType getAutoType(QualType DeducedType) const;
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
- QualType getTagDeclType(const TagDecl *Decl);
+ QualType getTagDeclType(const TagDecl *Decl) const;
/// 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).
@@ -716,14 +770,14 @@ public:
// getCFConstantStringType - Return the C structure type used to represent
// constant CFStrings.
- QualType getCFConstantStringType();
+ QualType getCFConstantStringType() const;
// getNSConstantStringType - Return the C structure type used to represent
// constant NSStrings.
- QualType getNSConstantStringType();
+ QualType getNSConstantStringType() const;
/// Get the structure type used to representation NSStrings, or NULL
/// if it hasn't yet been built.
- QualType getRawNSConstantStringType() {
+ QualType getRawNSConstantStringType() const {
if (NSConstantStringTypeDecl)
return getTagDeclType(NSConstantStringTypeDecl);
return QualType();
@@ -733,7 +787,7 @@ public:
/// Get the structure type used to representation CFStrings, or NULL
/// if it hasn't yet been built.
- QualType getRawCFConstantStringType() {
+ QualType getRawCFConstantStringType() const {
if (CFConstantStringTypeDecl)
return getTagDeclType(CFConstantStringTypeDecl);
return QualType();
@@ -747,11 +801,11 @@ public:
}
//// This gets the struct used to keep track of fast enumerations.
- QualType getObjCFastEnumerationStateType();
+ QualType getObjCFastEnumerationStateType() const;
/// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
/// been built.
- QualType getRawObjCFastEnumerationStateType() {
+ QualType getRawObjCFastEnumerationStateType() const {
if (ObjCFastEnumerationStateTypeDecl)
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
return QualType();
@@ -763,7 +817,7 @@ public:
void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
/// \brief Retrieve the C FILE type.
- QualType getFILEType() {
+ QualType getFILEType() const {
if (FILEDecl)
return getTypeDeclType(FILEDecl);
return QualType();
@@ -775,7 +829,7 @@ public:
}
/// \brief Retrieve the C jmp_buf type.
- QualType getjmp_bufType() {
+ QualType getjmp_bufType() const {
if (jmp_bufDecl)
return getTypeDeclType(jmp_bufDecl);
return QualType();
@@ -787,17 +841,22 @@ public:
}
/// \brief Retrieve the C sigjmp_buf type.
- QualType getsigjmp_bufType() {
+ QualType getsigjmp_bufType() const {
if (sigjmp_bufDecl)
return getTypeDeclType(sigjmp_bufDecl);
return QualType();
}
+ /// \brief The result type of logical operations, '<', '>', '!=', etc.
+ QualType getLogicalOperationType() const {
+ return getLangOptions().CPlusPlus ? BoolTy : IntTy;
+ }
+
/// 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,
- const FieldDecl *Field=0);
+ const FieldDecl *Field=0) const;
void getLegacyIntegralTypeEncoding(QualType &t) const;
@@ -805,13 +864,18 @@ public:
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
std::string &S) const;
+ /// getObjCEncodingForFunctionDecl - Returns the encoded type for this
+ //function. This is in the same format as Objective-C method encodings.
+ void getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
- void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
+ void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
+ const;
- /// getObjCEncodingForBlockDecl - Return the encoded type for this block
+ /// getObjCEncodingForBlock - Return the encoded type for this block
/// declaration.
- void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S);
+ std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
/// getObjCEncodingForPropertyDecl - Return the encoded type for
/// this method declaration. If non-NULL, Container must be either
@@ -819,14 +883,14 @@ public:
/// only be NULL when getting encodings for protocol properties.
void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
const Decl *Container,
- std::string &S);
+ std::string &S) const;
bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
- ObjCProtocolDecl *rProto);
+ ObjCProtocolDecl *rProto) const;
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose in characters.
- CharUnits getObjCEncodingTypeSize(QualType t);
+ CharUnits getObjCEncodingTypeSize(QualType t) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool isInt128Installed() const { return IsInt128Installed; }
@@ -854,12 +918,12 @@ public:
/// getCVRQualifiedType - Returns a type with additional const,
/// volatile, or restrict qualifiers.
- QualType getCVRQualifiedType(QualType T, unsigned CVR) {
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) const {
return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
}
/// getQualifiedType - Returns a type with additional qualifiers.
- QualType getQualifiedType(QualType T, Qualifiers Qs) {
+ QualType getQualifiedType(QualType T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return T.withFastQualifiers(Qs.getFastQualifiers());
QualifierCollector Qc(Qs);
@@ -868,35 +932,41 @@ public:
}
/// getQualifiedType - Returns a type with additional qualifiers.
- QualType getQualifiedType(const Type *T, Qualifiers Qs) {
+ QualType getQualifiedType(const Type *T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return QualType(T, Qs.getFastQualifiers());
return getExtQualType(T, Qs);
}
DeclarationNameInfo getNameForTemplate(TemplateName Name,
- SourceLocation NameLoc);
+ SourceLocation NameLoc) const;
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
- UnresolvedSetIterator End);
+ UnresolvedSetIterator End) const;
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
- TemplateDecl *Template);
+ TemplateDecl *Template) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
- const IdentifierInfo *Name);
+ const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
- OverloadedOperatorKind Operator);
-
+ OverloadedOperatorKind Operator) const;
+ TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+ const TemplateArgument &ArgPack) const;
+
enum GetBuiltinTypeError {
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);
+ /// GetBuiltinType - Return the type for the specified builtin. If
+ /// IntegerConstantArgs is non-null, it is filled in with a bitmask of
+ /// arguments to the builtin that are required to be integer constant
+ /// expressions.
+ QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
+ unsigned *IntegerConstantArgs = 0) const;
private:
CanQualType getFromTargetType(unsigned Type) const;
@@ -909,11 +979,12 @@ public:
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
- Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+ Qualifiers::GC getObjCGCAttrKind(QualType Ty) const;
- /// areCompatibleVectorTypes - Return true if the given vector types either
- /// are of the same unqualified type or if one is GCC and other - equivalent
- /// AltiVec vector type.
+ /// areCompatibleVectorTypes - Return true if the given vector types
+ /// are of the same unqualified type or if they are equivalent to the same
+ /// GCC vector type, ignoring whether they are target-specific (AltiVec or
+ /// Neon) types.
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
/// isObjCNSObjectType - Return true if this is an NSObject object with
@@ -930,76 +1001,83 @@ public:
/// 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) {
+ std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const;
+ std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const {
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) {
+ uint64_t getTypeSize(QualType T) const {
return getTypeInfo(T).first;
}
- uint64_t getTypeSize(const Type *T) {
+ uint64_t getTypeSize(const Type *T) const {
return getTypeInfo(T).first;
}
/// getCharWidth - Return the size of the character type, in bits
- uint64_t getCharWidth() {
+ uint64_t getCharWidth() const {
return getTypeSize(CharTy);
}
+ /// toCharUnitsFromBits - Convert a size in bits to a size in characters.
+ CharUnits toCharUnitsFromBits(int64_t BitSize) const;
+
+ /// toBits - Convert a size in characters to a size in bits.
+ int64_t toBits(CharUnits CharSize) const;
+
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
- CharUnits getTypeSizeInChars(QualType T);
- CharUnits getTypeSizeInChars(const Type *T);
+ CharUnits getTypeSizeInChars(QualType T) const;
+ CharUnits getTypeSizeInChars(const Type *T) const;
/// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
/// This method does not work on incomplete types.
- unsigned getTypeAlign(QualType T) {
+ unsigned getTypeAlign(QualType T) const {
return getTypeInfo(T).second;
}
- unsigned getTypeAlign(const Type *T) {
+ unsigned getTypeAlign(const Type *T) const {
return getTypeInfo(T).second;
}
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
/// characters. This method does not work on incomplete types.
- CharUnits getTypeAlignInChars(QualType T);
- CharUnits getTypeAlignInChars(const Type *T);
+ CharUnits getTypeAlignInChars(QualType T) const;
+ CharUnits getTypeAlignInChars(const Type *T) const;
- std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T);
- std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T);
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
/// 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);
+ unsigned getPreferredTypeAlign(const Type *T) const;
/// getDeclAlign - Return a conservative estimate of the alignment of
/// the specified decl. Note that bitfields do not have a valid alignment, so
/// this method will assert on them.
/// If @p RefAsPointee, references are treated like their underlying type
/// (for alignof), else they're treated like pointers (for CodeGen).
- CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false);
+ CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const;
/// 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);
+ const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
/// getASTObjCInterfaceLayout - Get or compute information about the
/// layout of the specified Objective-C interface.
- const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D);
+ const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D)
+ const;
- void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS);
+ void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS) const;
/// getASTObjCImplementationLayout - Get or compute information about
/// the layout of the specified Objective-C implementation. This may
/// differ from the interface if synthesized ivars are present.
const ASTRecordLayout &
- getASTObjCImplementationLayout(const ObjCImplementationDecl *D);
+ getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const;
/// getKeyFunction - Get the key function for the given record decl, or NULL
/// if there isn't one. The key function is, according to the Itanium C++ ABI
@@ -1009,13 +1087,18 @@ public:
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
+ bool isNearlyEmpty(const CXXRecordDecl *RD) const;
+
+ MangleContext *createMangleContext();
+
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars)
+ const;
void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const;
- unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
+ unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@@ -1029,8 +1112,11 @@ public:
/// 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.
- CanQualType getCanonicalType(QualType T);
- const Type *getCanonicalType(const Type *T) {
+ CanQualType getCanonicalType(QualType T) const {
+ return CanQualType::CreateUnsafe(T.getCanonicalType());
+ }
+
+ const Type *getCanonicalType(const Type *T) const {
return T->getCanonicalTypeInternal().getTypePtr();
}
@@ -1038,7 +1124,7 @@ public:
/// corresponding to the specific potentially non-canonical one.
/// Qualifiers are stripped off, functions are turned into function
/// pointers, and arrays decay one level into pointers.
- CanQualType getCanonicalParamType(QualType T);
+ CanQualType getCanonicalParamType(QualType T) const;
/// \brief Determine whether the given types are equivalent.
bool hasSameType(QualType T1, QualType T2) {
@@ -1062,13 +1148,8 @@ public:
/// \brief Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
- CanQualType CT1 = getCanonicalType(T1);
- CanQualType CT2 = getCanonicalType(T2);
-
- Qualifiers Quals;
- QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals);
- QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals);
- return UnqualT1 == UnqualT2;
+ return getCanonicalType(T1).getTypePtr() ==
+ getCanonicalType(T2).getTypePtr();
}
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
@@ -1097,11 +1178,15 @@ public:
/// by declarations in the type system and the canonical type for
/// the template type parameter 'T' is template-param-0-0.
NestedNameSpecifier *
- getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS);
+ getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
+
+ /// \brief Retrieves the default calling convention to use for
+ /// C++ instance methods.
+ CallingConv getDefaultMethodCallConv();
/// \brief Retrieves the canonical representation of the given
/// calling convention.
- CallingConv getCanonicalCallConv(CallingConv CC) {
+ CallingConv getCanonicalCallConv(CallingConv CC) const {
if (CC == CC_C)
return CC_Default;
return CC;
@@ -1131,7 +1216,7 @@ public:
/// template name uses the shortest form of the dependent
/// nested-name-specifier, which itself contains all canonical
/// types, values, and templates.
- TemplateName getCanonicalTemplateName(TemplateName Name);
+ TemplateName getCanonicalTemplateName(TemplateName Name) const;
/// \brief Determine whether the given template names refer to the same
/// template.
@@ -1142,33 +1227,35 @@ public:
/// 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);
+ TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
+ const;
/// 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
/// canonicalization, e.g. to move type qualifiers into the element type.
- const ArrayType *getAsArrayType(QualType T);
- const ConstantArrayType *getAsConstantArrayType(QualType T) {
+ const ArrayType *getAsArrayType(QualType T) const;
+ const ConstantArrayType *getAsConstantArrayType(QualType T) const {
return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
}
- const VariableArrayType *getAsVariableArrayType(QualType T) {
+ const VariableArrayType *getAsVariableArrayType(QualType T) const {
return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
}
- const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
+ const IncompleteArrayType *getAsIncompleteArrayType(QualType T) const {
return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
}
- const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) {
+ const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T)
+ const {
return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T));
}
/// getBaseElementType - Returns the innermost element type of an array type.
/// For example, will return "int" for int[m][n]
- QualType getBaseElementType(const ArrayType *VAT);
+ QualType getBaseElementType(const ArrayType *VAT) const;
/// getBaseElementType - Returns the innermost element type of a type
/// (which needn't actually be an array type).
- QualType getBaseElementType(QualType QT);
+ QualType getBaseElementType(QualType QT) const;
/// getConstantArrayElementCount - Returns number of constant array elements.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
@@ -1179,30 +1266,30 @@ public:
/// this returns a pointer to a properly qualified element of the array.
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
- QualType getArrayDecayedType(QualType T);
+ QualType getArrayDecayedType(QualType T) const;
/// 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);
+ QualType getPromotedIntegerType(QualType PromotableType) const;
/// \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);
+ QualType isPromotableBitField(Expr *E) const;
/// 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.
- int getIntegerTypeOrder(QualType LHS, QualType RHS);
+ int getIntegerTypeOrder(QualType LHS, QualType RHS) const;
/// 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.
- int getFloatingTypeOrder(QualType LHS, QualType RHS);
+ int getFloatingTypeOrder(QualType LHS, QualType RHS) const;
/// getFloatingTypeOfSizeWithinDomain - Returns a real floating
/// point or a complex type (based on typeDomain/typeSize).
@@ -1213,7 +1300,7 @@ public:
private:
// Helper for integer ordering
- unsigned getIntegerRank(Type* T);
+ unsigned getIntegerRank(const Type *T) const;
public:
@@ -1260,14 +1347,15 @@ public:
bool Unqualified = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
+ QualType mergeFunctionArgumentTypes(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeTransparentUnionType(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
QualType mergeObjCGCQualifiers(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);
-
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
@@ -1278,7 +1366,7 @@ public:
// The width of an integer, as defined in C99 6.2.6.2. This is the number
// of bits in an integer type excluding any padding bits.
- unsigned getIntWidth(QualType T);
+ unsigned getIntWidth(QualType T) const;
// Per C99 6.2.5p6, for every signed integer type, there is a corresponding
// unsigned integer type. This method takes a signed type, and returns the
@@ -1303,7 +1391,7 @@ public:
/// MakeIntValue - Make an APSInt of the appropriate width and
/// signedness for the given \arg Value and integer \arg Type.
- llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) {
+ llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType());
Res = Value;
return Res;
@@ -1314,12 +1402,23 @@ public:
/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+ /// \brief returns true if there is at lease one @implementation in TU.
+ bool AnyObjCImplementation() {
+ return !ObjCImpls.empty();
+ }
+
/// \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 Set the copy inialization expression of a block var decl.
+ void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+ /// \brief Get the copy initialization expression of VarDecl,or NULL if
+ /// none exists.
+ Expr *getBlockVarCopyInits(const VarDecl*VD);
/// \brief Allocate an uninitialized TypeSourceInfo.
///
@@ -1332,13 +1431,14 @@ public:
///
/// \param Size the size of the type info to create, or 0 if the size
/// should be calculated based on the type.
- TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0);
+ TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const;
/// \brief Allocate a TypeSourceInfo where all locations have been
/// initialized to a given location, which defaults to the empty
/// location.
TypeSourceInfo *
- getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation());
+ getTrivialTypeSourceInfo(QualType T,
+ SourceLocation Loc = SourceLocation()) const;
TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
@@ -1407,10 +1507,11 @@ private:
bool ExpandStructures,
const FieldDecl *Field,
bool OutermostType = false,
- bool EncodingProperty = false);
+ bool EncodingProperty = false) const;
- const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
- const ObjCImplementationDecl *Impl);
+ const ASTRecordLayout &
+ getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl) const;
private:
/// \brief A set of deallocations that should be performed when the
@@ -1423,8 +1524,8 @@ private:
llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
/// \brief A counter used to uniquely identify "blocks".
- unsigned int UniqueBlockByRefTypeID;
- unsigned int UniqueBlockParmTypeID;
+ mutable unsigned int UniqueBlockByRefTypeID;
+ mutable unsigned int UniqueBlockParmTypeID;
friend class DeclContext;
friend class DeclarationNameTable;
@@ -1469,7 +1570,7 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
/// @return The allocated memory. Could be NULL.
-inline void *operator new(size_t Bytes, clang::ASTContext &C,
+inline void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment) throw () {
return C.Allocate(Bytes, Alignment);
}
@@ -1479,7 +1580,7 @@ inline void *operator new(size_t Bytes, clang::ASTContext &C,
/// invoking it directly; see the new operator for more details. This operator
/// is called implicitly by the compiler if a placement new expression using
/// the ASTContext throws in the object constructor.
-inline void operator delete(void *Ptr, clang::ASTContext &C, size_t)
+inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
throw () {
C.Deallocate(Ptr);
}
@@ -1503,7 +1604,7 @@ inline void operator delete(void *Ptr, clang::ASTContext &C, size_t)
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
/// @return The allocated memory. Could be NULL.
-inline void *operator new[](size_t Bytes, clang::ASTContext& C,
+inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
size_t Alignment = 8) throw () {
return C.Allocate(Bytes, Alignment);
}
@@ -1514,7 +1615,7 @@ inline void *operator new[](size_t Bytes, clang::ASTContext& C,
/// invoking it directly; see the new[] operator for more details. This operator
/// is called implicitly by the compiler if a placement new[] expression using
/// the ASTContext throws in the object constructor.
-inline void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
throw () {
C.Deallocate(Ptr);
}
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 7cbf3a511705..1ab53b3e9148 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 9380058118c5..b659ce74bb7c 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -45,13 +45,13 @@ namespace clang {
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
-
- /// \brief The diagnostics object that we should use to emit diagnostics.
- Diagnostic &Diags;
+
+ /// \brief Whether to perform a minimal import.
+ bool Minimal;
/// \brief Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
- llvm::DenseMap<Type *, Type *> ImportedTypes;
+ llvm::DenseMap<const Type *, const Type *> ImportedTypes;
/// \brief Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
@@ -63,7 +63,7 @@ namespace clang {
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
- llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
+ llvm::DenseMap<FileID, FileID> ImportedFileIDs;
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
@@ -74,12 +74,29 @@ namespace clang {
NonEquivalentDeclSet NonEquivalentDecls;
public:
- ASTImporter(Diagnostic &Diags,
- ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager);
+ /// \brief Create a new AST importer.
+ ///
+ /// \param ToContext The context we'll be importing into.
+ ///
+ /// \param ToFileManager The file manager we'll be importing into.
+ ///
+ /// \param FromContext The context we'll be importing from.
+ ///
+ /// \param FromFileManager The file manager we'll be importing into.
+ ///
+ /// \param MinimalImport If true, the importer will attempt to import
+ /// as little as it can, e.g., by importing declarations as forward
+ /// declarations that can be completed at a later point.
+ ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport);
virtual ~ASTImporter();
+ /// \brief Whether the importer will perform a minimal import, creating
+ /// to-be-completed forward declarations when possible.
+ bool isMinimalImport() const { return Minimal; }
+
/// \brief Import the given type from the "from" context into the "to"
/// context.
///
@@ -129,6 +146,10 @@ namespace clang {
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
+ /// \brief Import the goven template name from the "from" context into the
+ /// "to" context.
+ TemplateName Import(TemplateName From);
+
/// \brief Import the given source location from the "from" context into
/// the "to" context.
///
@@ -154,7 +175,7 @@ namespace clang {
/// into the "to" context.
///
/// \returns the equivalent identifier in the "to" context.
- IdentifierInfo *Import(IdentifierInfo *FromId);
+ IdentifierInfo *Import(const IdentifierInfo *FromId);
/// \brief Import the given Objective-C selector from the "from"
/// context into the "to" context.
@@ -169,6 +190,12 @@ namespace clang {
/// context.
FileID Import(FileID);
+ /// \brief Import the definition of the given declaration, including all of
+ /// the declarations it contains.
+ ///
+ /// This routine is intended to be used
+ void ImportDefinition(Decl *From);
+
/// \brief Cope with a name conflict when importing a declaration into the
/// given context.
///
@@ -212,9 +239,6 @@ namespace clang {
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
-
- /// \brief Retrieve the diagnostic formatter.
- Diagnostic &getDiags() const { return Diags; }
/// \brief Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
@@ -228,12 +252,13 @@ namespace clang {
/// \brief Note that we have imported the "from" declaration by mapping it
/// to the (potentially-newly-created) "to" declaration.
///
- /// \returns \p To
- Decl *Imported(Decl *From, Decl *To);
+ /// Subclasses can override this function to observe all of the \c From ->
+ /// \c To declaration mappings as they are imported.
+ virtual Decl *Imported(Decl *From, Decl *To);
/// \brief Determine whether the given types are structurally
/// equivalent.
- bool IsStructurallyEquivalent(QualType From, QualType To);
+ bool IsStructurallyEquivalent(QualType From, QualType To);
};
}
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
new file mode 100644
index 000000000000..01e618024913
--- /dev/null
+++ b/include/clang/AST/ASTMutationListener.h
@@ -0,0 +1,48 @@
+//===--- ASTMutationListener.h - AST Mutation Interface --------*- 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 ASTMutationListener interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+
+namespace clang {
+ class Decl;
+ class DeclContext;
+ class TagDecl;
+ class CXXRecordDecl;
+ class ClassTemplateDecl;
+ class ClassTemplateSpecializationDecl;
+
+/// \brief An abstract interface that should be implemented by listeners
+/// that want to be notified when an AST entity gets modified after its
+/// initial creation.
+class ASTMutationListener {
+public:
+ virtual ~ASTMutationListener();
+
+ /// \brief A new TagDecl definition was completed.
+ virtual void CompletedTagDefinition(const TagDecl *D) { }
+
+ /// \brief A new declaration with name has been added to a DeclContext.
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
+
+ /// \brief An implicit member was added after the definition was completed.
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 62ca49fbf3b1..67968fde2d6b 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -36,19 +36,19 @@ namespace clang {
}
// Defined in ASTContext.h
-void *operator new(size_t Bytes, clang::ASTContext &C,
+void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 16) throw ();
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
-void *operator new[](size_t Bytes, clang::ASTContext &C,
+void *operator new[](size_t Bytes, const clang::ASTContext &C,
size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
-void operator delete(void *Ptr, clang::ASTContext &C, size_t)
+void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
throw ();
-void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
throw ();
namespace clang {
@@ -58,9 +58,10 @@ class Attr {
private:
SourceLocation Loc;
unsigned AttrKind : 16;
- bool Inherited : 1;
protected:
+ bool Inherited : 1;
+
virtual ~Attr();
void* operator new(size_t bytes) throw() {
@@ -88,10 +89,6 @@ protected:
public:
- /// \brief Whether this attribute should be merged to new
- /// declarations.
- virtual bool isMerged() const { return true; }
-
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
}
@@ -100,7 +97,6 @@ public:
void setLocation(SourceLocation L) { Loc = L; }
bool isInherited() const { return Inherited; }
- void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -109,6 +105,21 @@ public:
static bool classof(const Attr *) { return true; }
};
+class InheritableAttr : public Attr {
+protected:
+ InheritableAttr(attr::Kind AK, SourceLocation L)
+ : Attr(AK, L) {}
+
+public:
+ void setInherited(bool I) { Inherited = I; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() <= attr::LAST_INHERITABLE;
+ }
+ static bool classof(const InheritableAttr *) { return true; }
+};
+
#include "clang/AST/Attrs.inc"
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 5a84e404a1b6..2d30cb3b8b62 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include <list>
#include <map>
@@ -359,7 +360,11 @@ public:
/// subobjects of that type.
class CXXFinalOverriderMap
: public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };
-
+
+/// \brief A set of all the primary bases for a class.
+class CXXIndirectPrimaryBaseSet
+ : public llvm::SmallSet<const CXXRecordDecl*, 32> { };
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index dad4dfc926e1..4d7fcfd1d121 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -66,7 +66,16 @@ public:
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
- T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
+ ///
+ /// The underlying pointer must not be NULL.
+ const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
+
+ /// \brief Retrieve the underlying type pointer, which refers to a
+ /// canonical type, or NULL.
+ ///
+ const T *getTypePtrOrNull() const {
+ return cast_or_null<T>(Stored.getTypePtrOrNull());
+ }
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
@@ -78,6 +87,8 @@ public:
return Stored.isNull();
}
+ SplitQualType split() const { return Stored.split(); }
+
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
@@ -216,7 +227,7 @@ protected:
public:
/// \brief Retrieve the pointer to the underlying Type
- T* getTypePtr() const { return Stored.getTypePtr(); }
+ const T *getTypePtr() const { return Stored.getTypePtr(); }
/// \brief Implicit conversion to the underlying pointer.
///
@@ -225,7 +236,7 @@ public:
/// @code
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
/// @endcode
- operator const T*() const { return this->Stored.getTypePtr(); }
+ operator const T*() const { return this->Stored.getTypePtrOrNull(); }
/// \brief Try to convert the given canonical type to a specific structural
/// type.
@@ -336,7 +347,7 @@ namespace llvm {
/// to return smart pointer (proxies?).
template<typename T>
struct simplify_type<const ::clang::CanQual<T> > {
- typedef T* SimpleType;
+ typedef const T *SimpleType;
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
return Val.getTypePtr();
}
@@ -630,7 +641,6 @@ 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<>
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 0bb4b769d0f3..cf909e88220f 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -14,7 +14,9 @@
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
namespace clang {
@@ -131,12 +133,24 @@ namespace clang {
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
+ CharUnits operator- () const {
+ return CharUnits(-Quantity);
+ }
+
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
QuantityType getQuantity() const { return Quantity; }
+ /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is
+ /// greater than or equal to this quantity and is a multiple of \arg
+ /// Align. Align must be non-zero.
+ CharUnits RoundUpToAlignment(const CharUnits &Align) {
+ return CharUnits(llvm::RoundUpToAlignment(Quantity,
+ Align.Quantity));
+ }
+
}; // class CharUnit
} // namespace clang
@@ -146,4 +160,38 @@ inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
return CU * Scale;
}
+namespace llvm {
+
+template<> struct DenseMapInfo<clang::CharUnits> {
+ static clang::CharUnits getEmptyKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static clang::CharUnits getTombstoneKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static unsigned getHashValue(const clang::CharUnits &CU) {
+ clang::CharUnits::QuantityType Quantity = CU.getQuantity();
+ return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
+ }
+
+ static bool isEqual(const clang::CharUnits &LHS,
+ const clang::CharUnits &RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <> struct isPodLike<clang::CharUnits> {
+ static const bool value = true;
+};
+
+} // end namespace llvm
+
#endif // LLVM_CLANG_AST_CHARUNITS_H
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 674925532210..ee515da0835c 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -36,6 +36,7 @@ class FunctionTemplateSpecializationInfo;
class DependentFunctionTemplateSpecializationInfo;
class TypeLoc;
class UnresolvedSetImpl;
+class LabelStmt;
/// \brief A container of type source information.
///
@@ -196,9 +197,86 @@ public:
/// determine whether it's an instance member of its class.
bool isCXXInstanceMember() const;
+ class LinkageInfo {
+ Linkage linkage_;
+ Visibility visibility_;
+ bool explicit_;
+
+ public:
+ LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
+ explicit_(false) {}
+ LinkageInfo(Linkage L, Visibility V, bool E)
+ : linkage_(L), visibility_(V), explicit_(E) {}
+
+ static LinkageInfo external() {
+ return LinkageInfo();
+ }
+ static LinkageInfo internal() {
+ return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo uniqueExternal() {
+ return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo none() {
+ return LinkageInfo(NoLinkage, DefaultVisibility, false);
+ }
+
+ Linkage linkage() const { return linkage_; }
+ Visibility visibility() const { return visibility_; }
+ bool visibilityExplicit() const { return explicit_; }
+
+ void setLinkage(Linkage L) { linkage_ = L; }
+ void setVisibility(Visibility V) { visibility_ = V; }
+ void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
+ void setVisibility(LinkageInfo Other) {
+ setVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void mergeLinkage(Linkage L) {
+ setLinkage(minLinkage(linkage(), L));
+ }
+ void mergeLinkage(LinkageInfo Other) {
+ setLinkage(minLinkage(linkage(), Other.linkage()));
+ }
+
+ void mergeVisibility(Visibility V) {
+ setVisibility(minVisibility(visibility(), V));
+ }
+ void mergeVisibility(Visibility V, bool E) {
+ setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
+ }
+ void mergeVisibility(LinkageInfo Other) {
+ mergeVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void merge(LinkageInfo Other) {
+ mergeLinkage(Other);
+ mergeVisibility(Other);
+ }
+ void merge(std::pair<Linkage,Visibility> LV) {
+ mergeLinkage(LV.first);
+ mergeVisibility(LV.second);
+ }
+
+ friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
+ L.merge(R);
+ return L;
+ }
+ };
+
/// \brief Determine what kind of linkage this entity has.
Linkage getLinkage() const;
+ /// \brief Determines the visibility of this entity.
+ Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
+
+ /// \brief Determines the linkage and visibility of this entity.
+ LinkageInfo getLinkageAndVisibility() const;
+
+ /// \brief Clear the linkage cache in response to a change
+ /// to the declaration.
+ void ClearLinkageCache();
+
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl();
@@ -217,6 +295,29 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
return OS;
}
+/// LabelDecl - Represents the declaration of a label. Labels also have a
+/// corresponding LabelStmt, which indicates the position that the label was
+/// defined at. For normal labels, the location of the decl is the same as the
+/// location of the statement. For GNU local labels (__label__), the decl
+/// location is where the __label__ is.
+class LabelDecl : public NamedDecl {
+ LabelStmt *TheStmt;
+ LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S)
+ : NamedDecl(Label, DC, L, II), TheStmt(S) {}
+
+public:
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *II);
+
+ LabelStmt *getStmt() const { return TheStmt; }
+ void setStmt(LabelStmt *T) { TheStmt = T; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const LabelDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Label; }
+};
+
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext {
bool IsInline : 1;
@@ -232,7 +333,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to its anonymous namespace
- NamespaceDecl *NextNamespace;
+ LazyDeclPtr NextNamespace;
/// \brief A pointer to either the original namespace definition for
/// this namespace (if the boolean value is false) or the anonymous
@@ -250,7 +351,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
- IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
+ IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
@@ -281,8 +382,10 @@ public:
/// \brief Return the next extended namespace declaration or null if there
/// is none.
- NamespaceDecl *getNextNamespace() { return NextNamespace; }
- const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
+ NamespaceDecl *getNextNamespace();
+ const NamespaceDecl *getNextNamespace() const {
+ return const_cast<NamespaceDecl *>(this)->getNextNamespace();
+ }
/// \brief Set the next extended namespace declaration.
void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
@@ -331,9 +434,9 @@ public:
SourceLocation getLBracLoc() const { return LBracLoc; }
SourceLocation getRBracLoc() const { return RBracLoc; }
- void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
- void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
-
+ void setLBracLoc(SourceLocation L) { LBracLoc = L; }
+ void setRBracLoc(SourceLocation R) { RBracLoc = R; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceDecl *D) { return true; }
@@ -471,6 +574,9 @@ public:
static bool classofKind(Kind K) {
return K >= firstDeclarator && K <= lastDeclarator;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// \brief Structure used to store a statement, the constant value to
@@ -545,15 +651,21 @@ private:
/// \brief Whether this local variable could be allocated in the return
/// slot of its function, enabling the named return value optimization (NRVO).
bool NRVOVariable : 1;
+
+ /// \brief Whether this variable has a deduced C++0x auto type for which we're
+ /// currently parsing the initializer.
+ bool ParsingAutoInit : 1;
friend class StmtIteratorBase;
+ friend class ASTDeclReader;
+
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- ExceptionVar(false), NRVOVariable(false) {
+ ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -582,10 +694,7 @@ public:
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
- void setStorageClass(StorageClass SC) {
- assert(isLegalForVariable(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForVariable(SC));
SClassAsWritten = SC;
@@ -630,13 +739,13 @@ public:
/// external, C linkage.
bool isExternC() const;
- /// isBlockVarDecl - Returns true for local variable declarations. Note that
- /// this includes static variables inside of functions. It also includes
- /// variables inside blocks.
+ /// isLocalVarDecl - Returns true for local variable declarations
+ /// other than parameters. Note that this includes static variables
+ /// inside of functions. It also includes variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
///
- bool isBlockVarDecl() const {
+ bool isLocalVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
@@ -644,8 +753,8 @@ public:
return false;
}
- /// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes
- /// variables declared in blocks.
+ /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
+ /// excludes variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
@@ -683,6 +792,10 @@ public:
/// definition.
DefinitionKind isThisDeclarationADefinition() const;
+ /// \brief Check whether this variable is defined in this
+ /// translation unit.
+ DefinitionKind hasDefinition() const;
+
/// \brief Get the tentative definition that acts as the real definition in
/// a TU. Returns null if there is a proper definition available.
VarDecl *getActingDefinition();
@@ -733,7 +846,7 @@ public:
const Expr *getAnyInitializer(const VarDecl *&D) const;
bool hasInit() const {
- return !Init.isNull();
+ return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
}
const Expr *getInit() const {
if (Init.isNull())
@@ -776,6 +889,18 @@ public:
void setInit(Expr *I);
+ /// \brief Check whether we are in the process of parsing an initializer
+ /// needed to deduce the type of this variable.
+ bool isParsingAutoInit() const {
+ return ParsingAutoInit;
+ }
+
+ /// \brief Note whether we are currently parsing an initializer needed to
+ /// deduce the type of this variable.
+ void setParsingAutoInit(bool P) {
+ ParsingAutoInit = P;
+ }
+
EvaluatedStmt *EnsureEvaluatedStmt() const {
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
@@ -928,7 +1053,9 @@ class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {}
+ : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {
+ setImplicit();
+ }
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -1046,6 +1173,10 @@ public:
return getType();
}
+ /// \brief Determine whether this parameter is actually a function
+ /// parameter pack.
+ bool isParameterPack() 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
@@ -1096,13 +1227,13 @@ private:
unsigned SClass : 2;
unsigned SClassAsWritten : 2;
bool IsInline : 1;
+ bool IsInlineSpecified : 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;
/// \brief End part of this FunctionDecl's source range.
@@ -1136,19 +1267,54 @@ private:
/// declaration name embedded in the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
+ /// \brief Specify that this function declaration is actually a function
+ /// template specialization.
+ ///
+ /// \param C the ASTContext.
+ ///
+ /// \param Template the function template that this function template
+ /// specialization specializes.
+ ///
+ /// \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.
+ ///
+ /// \param TemplateArgsAsWritten location info of template arguments.
+ ///
+ /// \param PointOfInstantiation point at which the function template
+ /// specialization was first instantiated.
+ void setFunctionTemplateSpecialization(ASTContext &C,
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation);
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member function FD.
+ void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
+ TemplateSpecializationKind TSK);
+
+ void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams);
+
protected:
FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
- StorageClass S, StorageClass SCAsWritten, bool isInline)
+ StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK),
ParamInfo(0), Body(),
- SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
+ SClass(S), SClassAsWritten(SCAsWritten),
+ IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
- IsCopyAssignment(false),
- HasImplicitReturnZero(false),
- EndRangeLoc(NameInfo.getEndLoc()),
+ HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@@ -1169,11 +1335,11 @@ public:
TypeSourceInfo *TInfo,
StorageClass S = SC_None,
StorageClass SCAsWritten = SC_None,
- bool isInline = false,
+ bool isInlineSpecified = false,
bool hasWrittenPrototype = true) {
DeclarationNameInfo NameInfo(N, L);
return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
- isInline, hasWrittenPrototype);
+ isInlineSpecified, hasWrittenPrototype);
}
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1181,7 +1347,7 @@ public:
QualType T, TypeSourceInfo *TInfo,
StorageClass S = SC_None,
StorageClass SCAsWritten = SC_None,
- bool isInline = false,
+ bool isInlineSpecified = false,
bool hasWrittenPrototype = true);
DeclarationNameInfo getNameInfo() const {
@@ -1246,7 +1412,7 @@ public:
/// Whether this virtual function is pure, i.e. makes the containing class
/// abstract.
bool isPure() const { return IsPure; }
- void setPure(bool P = true) { IsPure = P; }
+ void setPure(bool P = true);
/// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors,
@@ -1255,9 +1421,6 @@ public:
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.
@@ -1273,7 +1436,6 @@ public:
}
bool hasWrittenPrototype() const { return HasWrittenPrototype; }
- void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; }
/// \brief Whether this function inherited its prototype from a
/// previous declaration.
@@ -1343,7 +1505,9 @@ public:
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
- void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
+ void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
+ setParams(getASTContext(), NewParamInfo, NumParams);
+ }
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
@@ -1361,31 +1525,32 @@ public:
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
- void setStorageClass(StorageClass SC) {
- assert(isLegalForFunction(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten);
}
- void setStorageClassAsWritten(StorageClass SC) {
- assert(isLegalForFunction(SC));
- SClassAsWritten = SC;
- }
/// \brief Determine whether the "inline" keyword was specified for this
/// function.
- bool isInlineSpecified() const { return IsInline; }
+ bool isInlineSpecified() const { return IsInlineSpecified; }
/// Set whether the "inline" keyword was specified for this function.
- void setInlineSpecified(bool I) { IsInline = I; }
+ void setInlineSpecified(bool I) {
+ IsInlineSpecified = I;
+ IsInline = I;
+ }
+
+ /// Flag that this function is implicitly inline.
+ void setImplicitlyInline() {
+ IsInline = true;
+ }
/// \brief Determine whether this function should be inlined, because it is
/// either marked "inline" or is a member function of a C++ class that
/// was defined in the class body.
bool isInlined() const;
-
+
bool isInlineDefinitionExternallyVisible() const;
/// isOverloadedOperator - Whether this function declaration
@@ -1432,7 +1597,9 @@ public:
/// \brief Specify that this record is an instantiation of the
/// member function FD.
void setInstantiationOfMemberFunction(FunctionDecl *FD,
- TemplateSpecializationKind TSK);
+ TemplateSpecializationKind TSK) {
+ setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
+ }
/// \brief Retrieves the function template that is described by this
/// function declaration.
@@ -1526,43 +1693,11 @@ public:
void *InsertPos,
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
const TemplateArgumentListInfo *TemplateArgsAsWritten = 0,
- SourceLocation PointOfInstantiation = SourceLocation());
-
- /// \brief Specify that this function declaration is actually a function
- /// template specialization.
- ///
- /// \param Template the function template that this function template
- /// specialization specializes.
- ///
- /// \param NumTemplateArgs number of template arguments that produced this
- /// function template specialization from the template.
- ///
- /// \param TemplateArgs array of template arguments that produced this
- /// function template specialization from the template.
- ///
- /// \param TSK the kind of template specialization this is.
- ///
- /// \param NumTemplateArgsAsWritten number of template arguments that produced
- /// this function template specialization from the template.
- ///
- /// \param TemplateArgsAsWritten array of location info for the template
- /// arguments.
- ///
- /// \param LAngleLoc location of left angle token.
- ///
- /// \param RAngleLoc location of right angle token.
- ///
- /// \param PointOfInstantiation point at which the function template
- /// specialization was first instantiated.
- void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
- unsigned NumTemplateArgs,
- const TemplateArgument *TemplateArgs,
- TemplateSpecializationKind TSK,
- unsigned NumTemplateArgsAsWritten,
- TemplateArgumentLoc *TemplateArgsAsWritten,
- SourceLocation LAngleLoc,
- SourceLocation RAngleLoc,
- SourceLocation PointOfInstantiation);
+ SourceLocation PointOfInstantiation = SourceLocation()) {
+ setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
+ InsertPos, TSK, TemplateArgsAsWritten,
+ PointOfInstantiation);
+ }
/// \brief Specifies that this function declaration is actually a
/// dependent function template specialization.
@@ -1620,19 +1755,26 @@ public:
class FieldDecl : public DeclaratorDecl {
// FIXME: This can be packed into the bitfields in Decl.
bool Mutable : 1;
+ mutable unsigned CachedFieldIndex : 31;
+
Expr *BitWidth;
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
Expr *BW, bool Mutable)
- : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) {
+ : DeclaratorDecl(DK, DC, L, Id, T, TInfo),
+ Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
}
public:
- static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
+ /// getFieldIndex - Returns the index of this field within its record,
+ /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
+ unsigned getFieldIndex() const;
+
/// isMutable - Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
@@ -1707,6 +1849,45 @@ public:
friend class StmtIteratorBase;
};
+/// IndirectFieldDecl - An instance of this class is created to represent a
+/// field injected from an anonymous union/struct into the parent scope.
+/// IndirectFieldDecl are always implicit.
+class IndirectFieldDecl : public ValueDecl {
+ NamedDecl **Chaining;
+ unsigned ChainingSize;
+
+ IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ NamedDecl **CH, unsigned CHS)
+ : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+
+public:
+ static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, NamedDecl **CH, unsigned CHS);
+
+ typedef NamedDecl * const *chain_iterator;
+ chain_iterator chain_begin() const { return Chaining; }
+ chain_iterator chain_end() const { return Chaining+ChainingSize; }
+
+ unsigned getChainingSize() const { return ChainingSize; }
+
+ FieldDecl *getAnonField() const {
+ assert(ChainingSize >= 2);
+ return cast<FieldDecl>(Chaining[ChainingSize - 1]);
+ }
+
+ VarDecl *getVarDecl() const {
+ assert(ChainingSize >= 2);
+ return dyn_cast<VarDecl>(*chain_begin());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const IndirectFieldDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == IndirectField; }
+ friend class ASTDeclReader;
+};
/// TypeDecl - Represents a declaration of a type.
///
@@ -1715,7 +1896,7 @@ class TypeDecl : public NamedDecl {
/// this TypeDecl. It is a cache maintained by
/// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
/// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
- mutable Type *TypeForDecl;
+ mutable const Type *TypeForDecl;
friend class ASTContext;
friend class DeclContext;
friend class TagDecl;
@@ -1729,8 +1910,8 @@ protected:
public:
// Low-level accessor
- Type *getTypeForDecl() const { return TypeForDecl; }
- void setTypeForDecl(Type *TD) { TypeForDecl = TD; }
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1820,6 +2001,19 @@ protected:
unsigned NumPositiveBits : 8;
unsigned NumNegativeBits : 8;
+ /// IsScoped - True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++0x mode.
+ bool IsScoped : 1;
+ /// IsScopedUsingClassTag - If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ bool IsScopedUsingClassTag : 1;
+
+ /// IsFixed - True if this is an enumeration with fixed underlying type. Only
+ /// possible in C++0x mode.
+ bool IsFixed : 1;
+
private:
SourceLocation TagKeywordLoc;
SourceLocation RBraceLoc;
@@ -1859,6 +2053,11 @@ protected:
typedef Redeclarable<TagDecl> redeclarable_base;
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+ /// @brief Completes the definition of this tag declaration.
+ ///
+ /// This is a helper function for derived classes.
+ void completeDefinition();
+
public:
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
@@ -1923,9 +2122,6 @@ public:
/// where it is in the process of being defined.
void startDefinition();
- /// @brief Completes the definition of this tag declaration.
- void completeDefinition();
-
/// 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
@@ -2001,7 +2197,19 @@ class EnumDecl : public TagDecl {
/// IntegerType - This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
- QualType IntegerType;
+ ///
+ /// If the underlying integer type was explicitly stated in the source
+ /// code, this is a TypeSourceInfo* for that type. Otherwise this type
+ /// was automatically deduced somehow, and this is a Type*.
+ ///
+ /// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in
+ /// some cases it won't.
+ ///
+ /// The underlying type of an enumeration never has any qualifiers, so
+ /// we can get away with just storing a raw Type*, and thus save an
+ /// extra pointer when TypeSourceInfo is needed.
+
+ llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;
/// PromotionType - The integer type that values of this type should
/// promote to. In C, enumerators are generally of an integer type
@@ -2022,11 +2230,16 @@ class EnumDecl : public TagDecl {
};
EnumDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
+ IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL,
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
- IntegerType = QualType();
+ assert(Scoped || !ScopedUsingClassTag);
+ IntegerType = (const Type*)0;
NumNegativeBits = 0;
NumPositiveBits = 0;
+ IsScoped = Scoped;
+ IsScopedUsingClassTag = ScopedUsingClassTag;
+ IsFixed = Fixed;
}
public:
EnumDecl *getCanonicalDecl() {
@@ -2045,7 +2258,9 @@ public:
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
- SourceLocation TKL, EnumDecl *PrevDecl);
+ SourceLocation TKL, EnumDecl *PrevDecl,
+ bool IsScoped, bool IsScopedUsingClassTag,
+ bool IsFixed);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
/// completeDefinition - When created, the EnumDecl corresponds to a
@@ -2085,10 +2300,25 @@ public:
/// getIntegerType - Return the integer type this enum decl corresponds to.
/// This returns a null qualtype for an enum forward definition.
- QualType getIntegerType() const { return IntegerType; }
+ QualType getIntegerType() const {
+ if (!IntegerType)
+ return QualType();
+ if (const Type* T = IntegerType.dyn_cast<const Type*>())
+ return QualType(T, 0);
+ return IntegerType.get<TypeSourceInfo*>()->getType();
+ }
/// \brief Set the underlying integer type.
- void setIntegerType(QualType T) { IntegerType = T; }
+ void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }
+
+ /// \brief Set the underlying integer type source info.
+ void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; }
+
+ /// \brief Return the type source info for the underlying integer type,
+ /// if no type source info exists, return 0.
+ TypeSourceInfo* getIntegerTypeSourceInfo() const {
+ return IntegerType.dyn_cast<TypeSourceInfo*>();
+ }
/// \brief Returns the width in bits requred to store all the
/// non-negative enumerators of this enum.
@@ -2116,6 +2346,27 @@ public:
NumNegativeBits = Num;
}
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScoped() const {
+ return IsScoped;
+ }
+
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScopedUsingClassTag() const {
+ return IsScopedUsingClassTag;
+ }
+
+ /// \brief Returns true if this is a C++0x enumeration with fixed underlying
+ /// type.
+ bool isFixed() const {
+ return IsFixed;
+ }
+
+ /// \brief Returns true if this can be considered a complete type.
+ bool isComplete() const {
+ return isDefinition() || isFixed();
+ }
+
/// \brief Returns the enumeration (declared within the template)
/// from which this enumeration type was instantiated, or NULL if
/// this enumeration was not instantiated from any template.
@@ -2128,6 +2379,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const EnumDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Enum; }
+
+ friend class ASTDeclReader;
};
@@ -2151,17 +2404,24 @@ class RecordDecl : public TagDecl {
/// containing an object.
bool HasObjectMember : 1;
+ /// \brief Whether the field declarations of this record have been loaded
+ /// from external storage. To avoid unnecessary deserialization of
+ /// methods/nested types we allow deserialization of just the fields
+ /// when needed.
+ mutable bool LoadedFieldsFromExternalStorage : 1;
+ friend class DeclContext;
+
protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL);
public:
- static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL = SourceLocation(),
RecordDecl* PrevDecl = 0);
- static RecordDecl *Create(ASTContext &C, EmptyShell Empty);
+ static RecordDecl *Create(const ASTContext &C, EmptyShell Empty);
const RecordDecl *getPreviousDeclaration() const {
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
@@ -2190,11 +2450,6 @@ public:
AnonymousStructOrUnion = Anon;
}
- ValueDecl *getAnonymousStructOrUnionObject();
- const ValueDecl *getAnonymousStructOrUnionObject() const {
- return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject();
- }
-
bool hasObjectMember() const { return HasObjectMember; }
void setHasObjectMember (bool val) { HasObjectMember = val; }
@@ -2229,11 +2484,10 @@ public:
// data members, functions, constructors, destructors, etc.
typedef specific_decl_iterator<FieldDecl> field_iterator;
- field_iterator field_begin() const {
- return field_iterator(decls_begin());
- }
+ field_iterator field_begin() const;
+
field_iterator field_end() const {
- return field_iterator(decls_end());
+ return field_iterator(decl_iterator());
}
// field_empty - Whether there are any fields (non-static data
@@ -2244,13 +2498,17 @@ public:
/// completeDefinition - Notes that the definition of this type is
/// now complete.
- void completeDefinition();
+ virtual void completeDefinition();
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const RecordDecl *D) { return true; }
static bool classofKind(Kind K) {
return K >= firstRecord && K <= lastRecord;
}
+
+private:
+ /// \brief Deserialize just the fields.
+ void LoadFieldsFromExternalStorage() const;
};
class FileScopeAsmDecl : public Decl {
@@ -2275,8 +2533,49 @@ public:
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
///
class BlockDecl : public Decl, public DeclContext {
+public:
+ /// A class which contains all the information about a particular
+ /// captured value.
+ class Capture {
+ enum {
+ flag_isByRef = 0x1,
+ flag_isNested = 0x2
+ };
+
+ /// The variable being captured.
+ llvm::PointerIntPair<VarDecl*, 2> VariableAndFlags;
+
+ /// The copy expression, expressed in terms of a DeclRef (or
+ /// BlockDeclRef) to the captured variable. Only required if the
+ /// variable has a C++ class type.
+ Expr *CopyExpr;
+
+ public:
+ Capture(VarDecl *variable, bool byRef, bool nested, Expr *copy)
+ : VariableAndFlags(variable,
+ (byRef ? flag_isByRef : 0) | (nested ? flag_isNested : 0)),
+ CopyExpr(copy) {}
+
+ /// The variable being captured.
+ VarDecl *getVariable() const { return VariableAndFlags.getPointer(); }
+
+ /// Whether this is a "by ref" capture, i.e. a capture of a __block
+ /// variable.
+ bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; }
+
+ /// Whether this is a nested capture, i.e. the variable captured
+ /// is not from outside the immediately enclosing function/block.
+ bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }
+
+ bool hasCopyExpr() const { return CopyExpr != 0; }
+ Expr *getCopyExpr() const { return CopyExpr; }
+ void setCopyExpr(Expr *e) { CopyExpr = e; }
+ };
+
+private:
// FIXME: This can be packed into the bitfields in Decl.
bool IsVariadic : 1;
+ bool CapturesCXXThis : 1;
/// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
@@ -2286,11 +2585,15 @@ class BlockDecl : public Decl, public DeclContext {
Stmt *Body;
TypeSourceInfo *SignatureAsWritten;
+ Capture *Captures;
+ unsigned NumCaptures;
+
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block),
- IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
- SignatureAsWritten(0) {}
+ IsVariadic(false), CapturesCXXThis(false),
+ ParamInfo(0), NumParams(0), Body(0),
+ SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
@@ -2319,7 +2622,7 @@ public:
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const { return ParamInfo+param_size(); }
- unsigned getNumParams() const;
+ unsigned getNumParams() const { return NumParams; }
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
@@ -2330,6 +2633,30 @@ public:
}
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
+ /// hasCaptures - True if this block (or its nested blocks) captures
+ /// anything of local storage from its enclosing scopes.
+ bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }
+
+ /// getNumCaptures - Returns the number of captured variables.
+ /// Does not include an entry for 'this'.
+ unsigned getNumCaptures() const { return NumCaptures; }
+
+ typedef const Capture *capture_iterator;
+ typedef const Capture *capture_const_iterator;
+ capture_iterator capture_begin() { return Captures; }
+ capture_iterator capture_end() { return Captures + NumCaptures; }
+ capture_const_iterator capture_begin() const { return Captures; }
+ capture_const_iterator capture_end() const { return Captures + NumCaptures; }
+
+ bool capturesCXXThis() const { return CapturesCXXThis; }
+
+ void setCaptures(ASTContext &Context,
+ const Capture *begin,
+ const Capture *end,
+ bool capturesCXXThis);
+
+ virtual SourceRange getSourceRange() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const BlockDecl *D) { return true; }
@@ -2350,6 +2677,32 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
+template<typename decl_type>
+void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
+ // Note: This routine is implemented here because we need both NamedDecl
+ // and Redeclarable to be defined.
+
+ decl_type *First;
+
+ if (PrevDecl) {
+ // Point to previous. Make sure that this is actually the most recent
+ // redeclaration, or we can build invalid chains. If the most recent
+ // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
+ RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
+ PrevDecl->getMostRecentDeclaration()));
+ 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));
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this)))
+ ND->ClearLinkageCache();
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 1369c2b5955a..bf249cea9d5f 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -43,6 +43,7 @@ class DeclarationName;
class CompoundStmt;
class StoredDeclsMap;
class DependentDiagnostic;
+class ASTMutationListener;
}
namespace llvm {
@@ -197,25 +198,25 @@ private:
return DeclCtx.get<DeclContext*>();
}
- /// Loc - The location that this decl.
+ /// Loc - The location of this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
- Kind DeclKind : 8;
+ unsigned DeclKind : 8;
/// InvalidDecl - This indicates a semantic error occurred.
- unsigned int InvalidDecl : 1;
+ unsigned InvalidDecl : 1;
/// HasAttrs - This indicates whether the decl has attributes or not.
- unsigned int HasAttrs : 1;
+ unsigned HasAttrs : 1;
/// Implicit - Whether this declaration was implicitly generated by
/// the implementation rather than explicitly written by the user.
- bool Implicit : 1;
+ unsigned Implicit : 1;
/// \brief Whether this declaration was "used", meaning that a definition is
/// required.
- bool Used : 1;
+ unsigned Used : 1;
protected:
/// Access - Used by C++ decls for the access specifier.
@@ -227,17 +228,24 @@ protected:
unsigned PCHLevel : 2;
/// ChangedAfterLoad - if this declaration has changed since being loaded
- bool ChangedAfterLoad : 1;
+ unsigned ChangedAfterLoad : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
- unsigned IdentifierNamespace : 15;
+ unsigned IdentifierNamespace : 12;
+ /// \brief Whether the \c CachedLinkage field is active.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned HasCachedLinkage : 1;
+
+ /// \brief If \c HasCachedLinkage, the linkage of this declaration.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned CachedLinkage : 2;
+
+
private:
-#ifndef NDEBUG
void CheckAccessDeclContext() const;
-#else
- void CheckAccessDeclContext() const { }
-#endif
protected:
@@ -246,7 +254,9 @@ protected:
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
@@ -254,7 +264,9 @@ protected:
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
@@ -272,7 +284,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- Kind getKind() const { return DeclKind; }
+ Kind getKind() const { return static_cast<Kind>(DeclKind); }
const char *getDeclKindName() const;
Decl *getNextDeclInContext() { return NextDeclInContext; }
@@ -298,17 +310,21 @@ public:
void setAccess(AccessSpecifier AS) {
Access = AS;
+#ifndef NDEBUG
CheckAccessDeclContext();
+#endif
}
AccessSpecifier getAccess() const {
+#ifndef NDEBUG
CheckAccessDeclContext();
+#endif
return AccessSpecifier(Access);
}
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs);
- AttrVec& getAttrs() {
+ AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
@@ -551,6 +567,9 @@ public:
/// template parameter pack.
bool isTemplateParameterPack() const;
+ /// \brief Whether this declaration is a parameter pack.
+ bool isParameterPack() const;
+
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;
@@ -621,10 +640,14 @@ public:
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
void dump() const;
+ void dumpXML() const;
+ void dumpXML(llvm::raw_ostream &OS) const;
private:
const Attr *getAttrsImpl() const;
+protected:
+ ASTMutationListener *getASTMutationListener() const;
};
/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
@@ -681,23 +704,24 @@ public:
///
class DeclContext {
/// DeclKind - This indicates which class this is.
- Decl::Kind DeclKind : 8;
+ unsigned DeclKind : 8;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are lexically
/// part of this context.
- mutable bool ExternalLexicalStorage : 1;
+ mutable unsigned ExternalLexicalStorage : 1;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are visible
/// in this context.
- mutable bool ExternalVisibleStorage : 1;
+ mutable unsigned ExternalVisibleStorage : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context).
mutable StoredDeclsMap *LookupPtr;
+protected:
/// FirstDecl - The first declaration stored within this declaration
/// context.
mutable Decl *FirstDecl;
@@ -710,7 +734,12 @@ class DeclContext {
friend class ExternalASTSource;
-protected:
+ /// \brief Build up a chain of declarations.
+ ///
+ /// \returns the first/last pair of declarations.
+ static std::pair<Decl *, Decl *>
+ BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls);
+
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
@@ -720,7 +749,7 @@ public:
~DeclContext();
Decl::Kind getDeclKind() const {
- return DeclKind;
+ return static_cast<Decl::Kind>(DeclKind);
}
const char *getDeclKindName() const;
@@ -807,6 +836,10 @@ public:
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
+ /// \brief Determines whether this context is, or is nested within,
+ /// a C++ extern "C" linkage spec.
+ bool isExternCContext() const;
+
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index a9802bfcaf4e..d11ee8f7fd64 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -35,6 +35,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class CXXMemberLookupCriteria;
class CXXFinalOverriderMap;
+class CXXIndirectPrimaryBaseSet;
class FriendDecl;
/// \brief Represents any kind of function declaration, whether it is a
@@ -112,6 +113,8 @@ class AccessSpecDecl : public Decl {
: Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) {
setAccess(AS);
}
+ AccessSpecDecl(EmptyShell Empty)
+ : Decl(AccessSpec, Empty) { }
public:
/// getAccessSpecifierLoc - The location of the access specifier.
SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
@@ -132,6 +135,9 @@ public:
SourceLocation ColonLoc) {
return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
}
+ static AccessSpecDecl *Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) AccessSpecDecl(Empty);
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -162,6 +168,10 @@ class CXXBaseSpecifier {
/// specifier (if present).
SourceRange Range;
+ /// \brief The source location of the ellipsis, if this is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
/// Virtual - Whether this is a virtual base class or not.
bool Virtual : 1;
@@ -177,6 +187,10 @@ class CXXBaseSpecifier {
/// VC++ bug.
unsigned Access : 2;
+ /// InheritConstructors - Whether the class contains a using declaration
+ /// to inherit the named class's constructors.
+ bool InheritConstructors : 1;
+
/// BaseTypeInfo - The type of the base class. This will be a class or struct
/// (or a typedef of such). The source code range does not include the
/// "virtual" or access specifier.
@@ -186,8 +200,9 @@ public:
CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
- TypeSourceInfo *TInfo)
- : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
+ TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
+ : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
+ Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@@ -201,6 +216,22 @@ public:
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
+ /// \brief Determine whether this base specifier is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+ /// \brief Determine whether this base class's constructors get inherited.
+ bool getInheritConstructors() const { return InheritConstructors; }
+
+ /// \brief Set that this base class's constructors should be inherited.
+ void setInheritConstructors(bool Inherit = true) {
+ InheritConstructors = Inherit;
+ }
+
+ /// \brief For a pack expansion, determine the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
/// getAccessSpecifier - Returns the access specifier for this base
/// specifier. This is the actual base specifier as used for
/// semantic analysis, so the result can never be AS_none. To
@@ -336,20 +367,20 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Whether we have already declared a destructor within the class.
bool DeclaredDestructor : 1;
-
- /// Bases - Base classes of this class.
- /// FIXME: This is wasted space for a union.
- CXXBaseSpecifier *Bases;
/// 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;
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ LazyCXXBaseSpecifiersPtr Bases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ LazyCXXBaseSpecifiersPtr VBases;
+
/// 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
@@ -371,6 +402,15 @@ class CXXRecordDecl : public RecordDecl {
/// in reverse order.
FriendDecl *FirstFriend;
+ /// \brief Retrieve the set of direct base classes.
+ CXXBaseSpecifier *getBases() const {
+ return Bases.get(Definition->getASTContext().getExternalSource());
+ }
+
+ /// \brief Retrieve the set of virtual base classes.
+ CXXBaseSpecifier *getVBases() const {
+ return VBases.get(Definition->getASTContext().getExternalSource());
+ }
} *DefinitionData;
struct DefinitionData &data() {
@@ -395,9 +435,17 @@ class CXXRecordDecl : public RecordDecl {
llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
TemplateOrInstantiation;
-#ifndef NDEBUG
- void CheckConversionFunction(NamedDecl *D);
-#endif
+ friend class DeclContext;
+
+ /// \brief Notify the class that member has been added.
+ ///
+ /// This routine helps maintain information about the class based on which
+ /// members have been added. It will be invoked by DeclContext::addDecl()
+ /// whenever a member is added to this record.
+ void addedMember(Decl *D);
+
+ void markedVirtualFunctionPure();
+ friend void FunctionDecl::setPure(bool);
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -445,12 +493,12 @@ public:
bool hasDefinition() const { return DefinitionData != 0; }
- static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL = SourceLocation(),
CXXRecordDecl* PrevDecl=0,
bool DelayTypeCreation = false);
- static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty);
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
@@ -463,8 +511,8 @@ public:
/// class.
unsigned getNumBases() const { return data().NumBases; }
- base_class_iterator bases_begin() { return data().Bases; }
- base_class_const_iterator bases_begin() const { return data().Bases; }
+ base_class_iterator bases_begin() { return data().getBases(); }
+ base_class_const_iterator bases_begin() const { return data().getBases(); }
base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
base_class_const_iterator bases_end() const {
return bases_begin() + data().NumBases;
@@ -486,8 +534,8 @@ public:
/// class.
unsigned getNumVBases() const { return data().NumVBases; }
- base_class_iterator vbases_begin() { return data().VBases; }
- base_class_const_iterator vbases_begin() const { return data().VBases; }
+ base_class_iterator vbases_begin() { return data().getVBases(); }
+ base_class_const_iterator vbases_begin() const { return data().getVBases(); }
base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
base_class_const_iterator vbases_end() const {
return vbases_begin() + data().NumVBases;
@@ -553,18 +601,12 @@ public:
return data().DeclaredDefaultConstructor;
}
- /// \brief Note whether this class has already had its default constructor
- /// implicitly declared or doesn't need one.
- void setDeclaredDefaultConstructor(bool DDC) {
- data().DeclaredDefaultConstructor = DDC;
- }
-
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
- bool hasConstCopyConstructor(ASTContext &Context) const;
+ bool hasConstCopyConstructor(const ASTContext &Context) const;
/// getCopyConstructor - Returns the copy constructor for this class
- CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
+ CXXConstructorDecl *getCopyConstructor(const ASTContext &Context,
unsigned TypeQuals) const;
/// \brief Retrieve the copy-assignment operator for this class, if available.
@@ -579,11 +621,6 @@ public:
/// a unique copy-assignment operator could not be found.
CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const;
- /// addedConstructor - Notify the class that another constructor has
- /// been added. This routine helps maintain information about the
- /// class based on which constructors have been added.
- void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
-
/// hasUserDeclaredConstructor - Whether this class has any
/// user-declared constructors. When true, a default constructor
/// will not be implicitly declared.
@@ -606,17 +643,6 @@ public:
return data().DeclaredCopyConstructor;
}
- /// \brief Note whether this class has already had its copy constructor
- /// declared.
- void setDeclaredCopyConstructor(bool DCC) {
- data().DeclaredCopyConstructor = DCC;
- }
-
- /// addedAssignmentOperator - Notify the class that another assignment
- /// operator has been added. This routine helps maintain information about the
- /// class based on which operators have been added.
- void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
-
/// hasUserDeclaredCopyAssignment - Whether this class has a
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
@@ -632,12 +658,6 @@ public:
return data().DeclaredCopyAssignment;
}
- /// \brief Note whether this class has already had its copy assignment
- /// operator declared.
- void setDeclaredCopyAssignment(bool DCA) {
- data().DeclaredCopyAssignment = DCA;
- }
-
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
@@ -645,26 +665,12 @@ public:
return data().UserDeclaredDestructor;
}
- /// 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) {
- data().UserDeclaredDestructor = UCD;
- if (UCD)
- data().DeclaredDestructor = true;
- }
-
/// \brief Determine whether this class has had its destructor declared,
/// either via the user or via an implicit declaration.
///
/// This value is used for lazy creation of destructors.
bool hasDeclaredDestructor() const { return data().DeclaredDestructor; }
-
- /// \brief Note whether this class has already had its destructor declared.
- void setDeclaredDestructor(bool DD) {
- data().DeclaredDestructor = DD;
- }
-
+
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
UnresolvedSetImpl *getConversionFunctions() {
@@ -682,13 +688,6 @@ public:
return getConversionFunctions()->end();
}
- /// Replaces a conversion function with a new declaration.
- ///
- /// Returns true if the old conversion was found.
- bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
- return getConversionFunctions()->replace(Old, New);
- }
-
/// Removes a conversion function from this class. The conversion
/// function must currently be a member of this class. Furthermore,
/// this class must currently be in the process of being defined.
@@ -698,105 +697,52 @@ public:
/// in current class; including conversion function templates.
const UnresolvedSetImpl *getVisibleConversionFunctions();
- /// addConversionFunction - Registers a conversion function which
- /// this class declares directly.
- void addConversionFunction(NamedDecl *Decl) {
-#ifndef NDEBUG
- CheckConversionFunction(Decl);
-#endif
-
- // We intentionally don't use the decl's access here because it
- // hasn't been set yet. That's really just a misdesign in Sema.
- data().Conversions.addDecl(Decl);
- }
-
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
/// constructors, no private or protected non-static data members,
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return data().Aggregate; }
- /// setAggregate - Set whether this class is an aggregate (C++
- /// [dcl.init.aggr]).
- void setAggregate(bool Agg) { data().Aggregate = Agg; }
-
- /// setMethodAsVirtual - Make input method virtual and set the necesssary
- /// special function bits and other bits accordingly.
- void setMethodAsVirtual(FunctionDecl *Method);
-
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
/// user-defined destructor.
bool isPOD() const { return data().PlainOldData; }
- /// setPOD - Set whether this class is a POD-type (C++ [class]p4).
- void setPOD(bool POD) { data().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 data().Empty; }
- /// Set whether this class is empty (C++0x [meta.unary.prop])
- void setEmpty(bool Emp) { data().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 data().Polymorphic; }
- /// setPolymorphic - Set whether this class is polymorphic (C++
- /// [class.virtual]).
- void setPolymorphic(bool Poly) { data().Polymorphic = Poly; }
-
/// 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 data().Abstract; }
- /// setAbstract - Set whether this class is abstract (C++ [class.abstract])
- void setAbstract(bool Abs) { data().Abstract = Abs; }
-
// hasTrivialConstructor - Whether this class has a trivial constructor
// (C++ [class.ctor]p5)
bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
- // setHasTrivialConstructor - Set whether this class has a trivial constructor
- // (C++ [class.ctor]p5)
- void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
-
// hasTrivialCopyConstructor - Whether this class has a trivial copy
// constructor (C++ [class.copy]p6)
bool hasTrivialCopyConstructor() const {
return data().HasTrivialCopyConstructor;
}
- // setHasTrivialCopyConstructor - Set whether this class has a trivial
- // copy constructor (C++ [class.copy]p6)
- void setHasTrivialCopyConstructor(bool TC) {
- data().HasTrivialCopyConstructor = TC;
- }
-
// hasTrivialCopyAssignment - Whether this class has a trivial copy
// assignment operator (C++ [class.copy]p11)
bool hasTrivialCopyAssignment() const {
return data().HasTrivialCopyAssignment;
}
- // setHasTrivialCopyAssignment - Set whether this class has a
- // trivial copy assignment operator (C++ [class.copy]p11)
- void setHasTrivialCopyAssignment(bool TC) {
- data().HasTrivialCopyAssignment = TC;
- }
-
// hasTrivialDestructor - Whether this class has a trivial destructor
// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
- // setHasTrivialDestructor - Set whether this class has a trivial destructor
- // (C++ [class.dtor]p3)
- void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
-
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
@@ -854,9 +800,6 @@ public:
/// \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();
/// getDestructor - Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
@@ -880,7 +823,7 @@ public:
/// \param Base the base class we are searching for.
///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(CXXRecordDecl *Base) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base) const;
/// \brief Determine whether this class is derived from the type \p Base.
///
@@ -898,7 +841,7 @@ public:
///
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
- bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// \brief Determine whether this class is virtually derived from
/// the class \p Base.
@@ -1034,6 +977,9 @@ public:
/// most-derived class in the class hierarchy.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
+ /// \brief Get the indirect primary bases for this class.
+ void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
+
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
@@ -1048,6 +994,27 @@ public:
return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
}
+ /// \brief Indicates that the definition of this class is now complete.
+ virtual void completeDefinition();
+
+ /// \brief Indicates that the definition of this class is now complete,
+ /// and provides a final overrider map to help determine
+ ///
+ /// \param FinalOverriders The final overrider map for this class, which can
+ /// be provided as an optimization for abstract-class checking. If NULL,
+ /// final overriders will be computed if they are needed to complete the
+ /// definition.
+ void completeDefinition(CXXFinalOverriderMap *FinalOverriders);
+
+ /// \brief Determine whether this class may end up being abstract, even though
+ /// it is not yet known to be abstract.
+ ///
+ /// \returns true if this class is not known to be abstract but has any
+ /// base classes that are abstract. In this case, \c completeDefinition()
+ /// will need to compute final overriders to determine whether the class is
+ /// actually abstract.
+ bool mayBeAbstract() const;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstCXXRecord && K <= lastCXXRecord;
@@ -1059,6 +1026,8 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
};
/// CXXMethodDecl - Represents a static or instance method of a
@@ -1139,6 +1108,20 @@ public:
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}
+ /// \brief Retrieve the ref-qualifier associated with this method.
+ ///
+ /// In the following example, \c f() has an lvalue ref-qualifier, \c g()
+ /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier.
+ /// \code
+ /// struct X {
+ /// void f() &;
+ /// void g() &&;
+ /// void h();
+ /// };
+ RefQualifierKind getRefQualifier() const {
+ return getType()->getAs<FunctionProtoType>()->getRefQualifier();
+ }
+
bool hasInlineBody() const;
// Implement isa/cast/dyncast/etc.
@@ -1149,7 +1132,7 @@ public:
}
};
-/// CXXBaseOrMemberInitializer - Represents a C++ base or member
+/// CXXCtorInitializer - Represents a C++ base or member
/// initializer, which is part of a constructor initializer that
/// initializes one non-static member variable or one base class. For
/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
@@ -1163,37 +1146,20 @@ public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// @endcode
-class CXXBaseOrMemberInitializer {
- /// \brief Either the base class name (stored as a TypeSourceInfo*) or the
- /// field being initialized.
- llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember;
+class CXXCtorInitializer {
+ /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal
+ /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being
+ /// initialized.
+ llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
+ Initializee;
- /// \brief The source location for the field name.
- SourceLocation MemberLocation;
+ /// \brief The source location for the field name or, for a base initializer
+ /// pack expansion, the location of the ellipsis.
+ SourceLocation MemberOrEllipsisLocation;
/// \brief The argument used to initialize the base or member, which may
/// end up constructing an object (when multiple arguments are involved).
Stmt *Init;
-
- /// \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.
- FieldDecl *AnonUnionMember;
/// LParenLoc - Location of the left paren of the ctor-initializer.
SourceLocation LParenLoc;
@@ -1208,6 +1174,7 @@ class CXXBaseOrMemberInitializer {
/// IsWritten - Whether or not the initializer is explicitly written
/// in the sources.
bool IsWritten : 1;
+
/// SourceOrderOrNumArrayIndices - If IsWritten is true, then this
/// number keeps track of the textual order of this initializer in the
/// original sources, counting from 0; otherwise, if IsWritten is false,
@@ -1215,50 +1182,62 @@ class CXXBaseOrMemberInitializer {
/// object in memory.
unsigned SourceOrderOrNumArrayIndices : 14;
- CXXBaseOrMemberInitializer(ASTContext &Context,
- FieldDecl *Member, SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices);
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
public:
- /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
+ /// CXXCtorInitializer - Creates a new base-class initializer.
explicit
- CXXBaseOrMemberInitializer(ASTContext &Context,
- TypeSourceInfo *TInfo, bool IsVirtual,
- SourceLocation L,
- Expr *Init,
- SourceLocation R);
+ CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
+ SourceLocation L, Expr *Init, SourceLocation R,
+ SourceLocation EllipsisLoc);
- /// CXXBaseOrMemberInitializer - Creates a new member initializer.
+ /// CXXCtorInitializer - Creates a new member initializer.
explicit
- CXXBaseOrMemberInitializer(ASTContext &Context,
- FieldDecl *Member, SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R);
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ explicit
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
/// \brief Creates a new member initializer that optionally contains
/// array indices used to describe an elementwise initialization.
- static CXXBaseOrMemberInitializer *Create(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices);
+ static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L,
+ Expr *Init, SourceLocation R,
+ VarDecl **Indices, unsigned NumIndices);
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
- bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
+ bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); }
/// isMemberInitializer - Returns true when this initializer is
/// initializing a non-static data member.
- bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); }
+ bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); }
+
+ bool isAnyMemberInitializer() const {
+ return isMemberInitializer() || isIndirectMemberInitializer();
+ }
+ bool isIndirectMemberInitializer() const {
+ return Initializee.is<IndirectFieldDecl*>();
+ }
+
+ /// \brief Determine whether this initializer is a pack expansion.
+ bool isPackExpansion() const {
+ return isBaseInitializer() && MemberOrEllipsisLocation.isValid();
+ }
+
+ // \brief For a pack expansion, returns the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ assert(isPackExpansion() && "Initializer is not a pack expansion");
+ return MemberOrEllipsisLocation;
+ }
+
/// If this is a base class initializer, returns the type of the
/// base class with location information. Otherwise, returns an NULL
/// type location.
@@ -1267,7 +1246,6 @@ public:
/// If this is a base class initializer, returns the type of the base class.
/// Otherwise, returns NULL.
const Type *getBaseClass() const;
- Type *getBaseClass();
/// Returns whether the base is virtual or not.
bool isBaseVirtual() const {
@@ -1278,7 +1256,7 @@ public:
/// \brief Returns the declarator information for a base class initializer.
TypeSourceInfo *getBaseClassInfo() const {
- return BaseOrMember.dyn_cast<TypeSourceInfo *>();
+ return Initializee.dyn_cast<TypeSourceInfo *>();
}
/// getMember - If this is a member initializer, returns the
@@ -1286,18 +1264,28 @@ public:
/// initialized. Otherwise, returns NULL.
FieldDecl *getMember() const {
if (isMemberInitializer())
- return BaseOrMember.get<FieldDecl*>();
+ return Initializee.get<FieldDecl*>();
+ else
+ return 0;
+ }
+ FieldDecl *getAnyMember() const {
+ if (isMemberInitializer())
+ return Initializee.get<FieldDecl*>();
+ else if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>()->getAnonField();
else
return 0;
}
- SourceLocation getMemberLocation() const {
- return MemberLocation;
+ IndirectFieldDecl *getIndirectMember() const {
+ if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>();
+ else
+ return 0;
}
- void setMember(FieldDecl *Member) {
- assert(isMemberInitializer());
- BaseOrMember = Member;
+ SourceLocation getMemberLocation() const {
+ return MemberOrEllipsisLocation;
}
/// \brief Determine the source location of the initializer.
@@ -1329,15 +1317,7 @@ public:
IsWritten = true;
SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos);
}
-
- FieldDecl *getAnonUnionMember() const {
- return AnonUnionMember;
- }
- void setAnonUnionMember(FieldDecl *anonMember) {
- AnonUnionMember = anonMember;
- }
-
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -1388,10 +1368,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
bool ImplicitlyDefined : 1;
/// Support for base and member initializers.
- /// BaseOrMemberInitializers - The arguments used to initialize the base
+ /// CtorInitializers - The arguments used to initialize the base
/// or member.
- CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
- unsigned NumBaseOrMemberInitializers;
+ CXXCtorInitializer **CtorInitializers;
+ unsigned NumCtorInitializers;
CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
@@ -1400,7 +1380,7 @@ class CXXConstructorDecl : public CXXMethodDecl {
: CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
- BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
+ CtorInitializers(0), NumCtorInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -1443,37 +1423,54 @@ public:
}
/// init_iterator - Iterates through the member/base initializer list.
- typedef CXXBaseOrMemberInitializer **init_iterator;
+ typedef CXXCtorInitializer **init_iterator;
/// init_const_iterator - Iterates through the memberbase initializer list.
- typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+ typedef CXXCtorInitializer * const * init_const_iterator;
/// init_begin() - Retrieve an iterator to the first initializer.
- init_iterator init_begin() { return BaseOrMemberInitializers; }
+ init_iterator init_begin() { return CtorInitializers; }
/// begin() - Retrieve an iterator to the first initializer.
- init_const_iterator init_begin() const { return BaseOrMemberInitializers; }
+ init_const_iterator init_begin() const { return CtorInitializers; }
/// init_end() - Retrieve an iterator past the last initializer.
init_iterator init_end() {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ return CtorInitializers + NumCtorInitializers;
}
/// end() - Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ return CtorInitializers + NumCtorInitializers;
+ }
+
+ typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
+ typedef std::reverse_iterator<init_const_iterator> init_const_reverse_iterator;
+
+ init_reverse_iterator init_rbegin() {
+ return init_reverse_iterator(init_end());
+ }
+ init_const_reverse_iterator init_rbegin() const {
+ return init_const_reverse_iterator(init_end());
+ }
+
+ init_reverse_iterator init_rend() {
+ return init_reverse_iterator(init_begin());
+ }
+ init_const_reverse_iterator init_rend() const {
+ return init_const_reverse_iterator(init_begin());
}
/// getNumArgs - Determine the number of arguments used to
/// initialize the member or base.
- unsigned getNumBaseOrMemberInitializers() const {
- return NumBaseOrMemberInitializers;
+ unsigned getNumCtorInitializers() const {
+ return NumCtorInitializers;
}
- void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) {
- NumBaseOrMemberInitializers = numBaseOrMemberInitializers;
+ void setNumCtorInitializers(unsigned numCtorInitializers) {
+ NumCtorInitializers = numCtorInitializers;
}
- void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) {
- BaseOrMemberInitializers = initializers;
+ void setCtorInitializers(CXXCtorInitializer ** initializers) {
+ CtorInitializers = initializers;
}
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
@@ -1502,15 +1499,44 @@ public:
return isCopyConstructor(TypeQuals);
}
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ ///
+ /// \param TypeQuals If this constructor is a move constructor, will be set
+ /// to the type qualifiers on the referent of the first parameter's type.
+ bool isMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ bool isMoveConstructor() const;
+
+ /// \brief Determine whether this is a copy or move constructor.
+ ///
+ /// \param TypeQuals Will be set to the type qualifiers on the reference
+ /// parameter, if in fact this is a copy or move constructor.
+ bool isCopyOrMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this a copy or move constructor.
+ bool isCopyOrMoveConstructor() const {
+ unsigned Quals;
+ return isCopyOrMoveConstructor(Quals);
+ }
+
/// isConvertingConstructor - Whether this constructor is a
/// converting constructor (C++ [class.conv.ctor]), which can be
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
/// \brief Determine whether this is a member template specialization that
- /// looks like a copy constructor. Such constructors are never used to copy
+ /// would copy the object to itself. Such constructors are never used to copy
/// an object.
- bool isCopyConstructorLikeSpecialization() const;
+ bool isSpecializationCopyingObject() const;
+
+ /// \brief Get the constructor that this inheriting constructor is based on.
+ const CXXConstructorDecl *getInheritedConstructor() const;
+
+ /// \brief Set the constructor that this inheriting constructor is based on.
+ void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1542,8 +1568,9 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete;
CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
- QualType T, bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
@@ -1553,7 +1580,8 @@ public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
- QualType T, bool isInline,
+ QualType T, TypeSourceInfo* TInfo,
+ bool isInline,
bool isImplicitlyDeclared);
/// isImplicitlyDefined - Whether this destructor was implicitly
@@ -1918,13 +1946,16 @@ class UsingShadowDecl : public NamedDecl {
/// The referenced declaration.
NamedDecl *Underlying;
- /// The using declaration which introduced this decl.
- UsingDecl *Using;
+ /// \brief The using declaration which introduced this decl or the next using
+ /// shadow declaration contained in the aforementioned using declaration.
+ NamedDecl *UsingOrNextShadow;
+ friend class UsingDecl;
UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target)
: NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
- Underlying(Target), Using(Using) {
+ Underlying(Target),
+ UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
if (Target) {
setDeclName(Target->getDeclName());
IdentifierNamespace = Target->getIdentifierNamespace();
@@ -1952,15 +1983,20 @@ public:
}
/// \brief Gets the using declaration to which this declaration is tied.
- UsingDecl *getUsingDecl() const { return Using; }
+ UsingDecl *getUsingDecl() const;
- /// \brief Sets the using declaration that introduces this target
- /// declaration.
- void setUsingDecl(UsingDecl* UD) { Using = UD; }
+ /// \brief The next using shadow declaration contained in the shadow decl
+ /// chain of the using declaration which introduced this decl.
+ UsingShadowDecl *getNextUsingShadowDecl() const {
+ return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow);
+ }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingShadowDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// UsingDecl - Represents a C++ using-declaration. For example:
@@ -1980,10 +2016,9 @@ class UsingDecl : public NamedDecl {
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
- /// \brief The collection of shadow declarations associated with
- /// this using declaration. This set can change as a class is
- /// processed.
- llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
+ /// \brief The first shadow declaration of the shadow decl chain associated
+ /// with this using declaration.
+ UsingShadowDecl *FirstUsingShadow;
// \brief Has 'typename' keyword.
bool IsTypeName;
@@ -1993,7 +2028,7 @@ class UsingDecl : public NamedDecl {
const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
- DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
}
public:
@@ -2031,29 +2066,58 @@ public:
/// \brief Sets whether the using declaration has 'typename'.
void setTypeName(bool TN) { IsTypeName = TN; }
- typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
- shadow_iterator shadow_begin() const { return Shadows.begin(); }
- shadow_iterator shadow_end() const { return Shadows.end(); }
+ /// \brief Iterates through the using shadow declarations assosiated with
+ /// this using declaration.
+ class shadow_iterator {
+ /// \brief The current using shadow declaration.
+ UsingShadowDecl *Current;
+
+ public:
+ typedef UsingShadowDecl* value_type;
+ typedef UsingShadowDecl* reference;
+ typedef UsingShadowDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ shadow_iterator() : Current(0) { }
+ explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
- void addShadowDecl(UsingShadowDecl *S) {
- assert(S->getUsingDecl() == this);
- if (!Shadows.insert(S)) {
- assert(false && "declaration already in set");
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ shadow_iterator& operator++() {
+ Current = Current->getNextUsingShadowDecl();
+ return *this;
}
- }
- void removeShadowDecl(UsingShadowDecl *S) {
- assert(S->getUsingDecl() == this);
- if (!Shadows.erase(S)) {
- assert(false && "declaration not in set");
+
+ shadow_iterator operator++(int) {
+ shadow_iterator tmp(*this);
+ ++(*this);
+ return tmp;
}
+
+ friend bool operator==(shadow_iterator x, shadow_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(shadow_iterator x, shadow_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ shadow_iterator shadow_begin() const {
+ return shadow_iterator(FirstUsingShadow);
}
+ shadow_iterator shadow_end() const { return shadow_iterator(); }
/// \brief Return the number of shadowed declarations associated with this
/// using declaration.
- unsigned getNumShadowDecls() const {
- return Shadows.size();
+ unsigned shadow_size() const {
+ return std::distance(shadow_begin(), shadow_end());
}
+ void addShadowDecl(UsingShadowDecl *S);
+ void removeShadowDecl(UsingShadowDecl *S);
+
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
SourceRange NNR, SourceLocation UsingL,
NestedNameSpecifier* TargetNNS,
@@ -2145,6 +2209,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// UnresolvedUsingTypenameDecl - Represents a dependent using
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 4b5e6fd48bb3..20d6da19b8ca 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -43,11 +43,16 @@ private:
FriendUnion Friend;
// A pointer to the next friend in the sequence.
- FriendDecl *NextFriend;
+ LazyDeclPtr NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
+ /// True if this 'friend' declaration is unsupported. Eventually we
+ /// will support every possible friend declaration, but for now we
+ /// silently ignore some and set this flag to authorize all access.
+ bool UnsupportedFriend;
+
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
@@ -55,13 +60,19 @@ private:
SourceLocation FriendL)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
- NextFriend(0),
- FriendLoc(FriendL) {
+ NextFriend(),
+ FriendLoc(FriendL),
+ UnsupportedFriend(false) {
}
explicit FriendDecl(EmptyShell Empty)
- : Decl(Decl::Friend, Empty), NextFriend(0) { }
+ : Decl(Decl::Friend, Empty), NextFriend() { }
+ FriendDecl *getNextFriend() {
+ return cast_or_null<FriendDecl>(
+ NextFriend.get(getASTContext().getExternalSource()));
+ }
+
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
@@ -87,6 +98,14 @@ public:
return FriendLoc;
}
+ /// Determines if this friend kind is unsupported.
+ bool isUnsupportedFriend() const {
+ return UnsupportedFriend;
+ }
+ void setUnsupportedFriend(bool Unsupported) {
+ UnsupportedFriend = Unsupported;
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const FriendDecl *D) { return true; }
@@ -115,7 +134,7 @@ public:
friend_iterator &operator++() {
assert(Ptr && "attempt to increment past end of friend list");
- Ptr = Ptr->NextFriend;
+ Ptr = Ptr->getNextFriend();
return *this;
}
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 030291ea7345..cb9e1681cc06 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace clang {
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index ad26748e1343..b3ca474fcc19 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -28,7 +28,7 @@ class ObjCProtocolDecl;
class ObjCCategoryDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
-class CXXBaseOrMemberInitializer;
+class CXXCtorInitializer;
class ObjCListBase {
void operator=(const ObjCListBase &); // DO NOT IMPLEMENT
@@ -437,7 +437,7 @@ public:
class ObjCInterfaceDecl : public ObjCContainerDecl {
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
- mutable Type *TypeForDecl;
+ mutable const Type *TypeForDecl;
friend class ASTContext;
/// Class's super class.
@@ -449,8 +449,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Protocols reference in both the @interface and class extensions.
ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
- /// List of categories defined for this class.
- /// FIXME: Why is this a linked list??
+ /// \brief List of categories and class extensions defined for this class.
+ ///
+ /// Categories are stored as a linked list in the AST, since the categories
+ /// and class extensions come long after the initial interface declaration,
+ /// and we avoid dynamically-resized arrays in the AST whereever possible.
ObjCCategoryDecl *CategoryList;
/// IvarList - List of all ivars defined by this class; including class
@@ -459,7 +462,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
-
+
+ /// \brief Indicates that the contents of this Objective-C class will be
+ /// completed by the external AST source when required.
+ mutable bool ExternallyCompleted : 1;
+
SourceLocation ClassLoc; // location of the class identifier.
SourceLocation SuperClassLoc; // location of the super class identifier.
SourceLocation EndLoc; // marks the '>', '}', or identifier.
@@ -467,6 +474,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal);
+ void LoadExternalDefinition() const;
public:
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
@@ -474,7 +482,16 @@ public:
SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false,
bool isInternal = false);
+
+ /// \brief Indicate that this Objective-C class is complete, but that
+ /// the external AST source will be responsible for filling in its contents
+ /// when a complete class is required.
+ void setExternallyCompleted();
+
const ObjCProtocolList &getReferencedProtocols() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols;
}
@@ -494,29 +511,47 @@ public:
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.begin();
}
protocol_iterator protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.end();
}
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.loc_end();
}
typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
all_protocol_iterator all_referenced_protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return AllReferencedProtocols.empty() ? protocol_begin()
: AllReferencedProtocols.begin();
}
all_protocol_iterator all_referenced_protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return AllReferencedProtocols.empty() ? protocol_end()
: AllReferencedProtocols.end();
}
@@ -551,10 +586,22 @@ public:
bool isForwardDecl() const { return ForwardDecl; }
void setForwardDecl(bool val) { ForwardDecl = val; }
- ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ ObjCInterfaceDecl *getSuperClass() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return SuperClass;
+ }
+
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
- ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
+ ObjCCategoryDecl* getCategoryList() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return CategoryList;
+ }
+
void setCategoryList(ObjCCategoryDecl *category) {
CategoryList = category;
}
@@ -595,7 +642,7 @@ public:
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
// Lookup a method in the classes implementation hierarchy.
- ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel);
+ ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true);
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
@@ -621,8 +668,8 @@ public:
bool RHSIsQualifiedID = false);
// Low-level accessor
- Type *getTypeForDecl() const { return TypeForDecl; }
- void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
@@ -991,6 +1038,7 @@ public:
void insertNextClassCategory() {
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
+ ClassInterface->setChangedSinceDeserialization(true);
}
bool IsClassExtension() const { return getIdentifier() == 0; }
@@ -1168,7 +1216,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
ObjCInterfaceDecl *SuperClass;
/// Support for ivar initialization.
/// IvarInitializers - The arguments used to initialize the ivars
- CXXBaseOrMemberInitializer **IvarInitializers;
+ CXXCtorInitializer **IvarInitializers;
unsigned NumIvarInitializers;
/// true of class extension has at least one bitfield ivar.
@@ -1187,10 +1235,10 @@ public:
ObjCInterfaceDecl *superDecl);
/// init_iterator - Iterates through the ivar initializer list.
- typedef CXXBaseOrMemberInitializer **init_iterator;
+ typedef CXXCtorInitializer **init_iterator;
/// init_const_iterator - Iterates through the ivar initializer list.
- typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+ typedef CXXCtorInitializer * const * init_const_iterator;
/// init_begin() - Retrieve an iterator to the first initializer.
init_iterator init_begin() { return IvarInitializers; }
@@ -1215,7 +1263,7 @@ public:
}
void setIvarInitializers(ASTContext &C,
- CXXBaseOrMemberInitializer ** initializers,
+ CXXCtorInitializer ** initializers,
unsigned numInitializers);
bool hasSynthBitfield() const { return HasSynthBitfield; }
@@ -1322,7 +1370,8 @@ public:
OBJC_PR_retain = 0x10,
OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
- OBJC_PR_setter = 0x80
+ OBJC_PR_setter = 0x80,
+ OBJC_PR_atomic = 0x100
};
enum SetterKind { Assign, Retain, Copy };
@@ -1330,8 +1379,8 @@ public:
private:
SourceLocation AtLoc; // location of @property
TypeSourceInfo *DeclType;
- unsigned PropertyAttributes : 8;
- unsigned PropertyAttributesAsWritten : 8;
+ unsigned PropertyAttributes : 9;
+ unsigned PropertyAttributesAsWritten : 9;
// @required/@optional
unsigned PropertyImplementation : 2;
@@ -1429,6 +1478,10 @@ public:
return PropertyIvarDecl;
}
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getLocation());
+ }
+
/// Lookup a property by name in the specified DeclContext.
static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
IdentifierInfo *propertyID);
@@ -1450,6 +1503,15 @@ public:
};
private:
SourceLocation AtLoc; // location of @synthesize or @dynamic
+
+ /// \brief For @synthesize, the location of the ivar, if it was written in
+ /// the source code.
+ ///
+ /// \code
+ /// @synthesize int a = b
+ /// \endcode
+ SourceLocation IvarLoc;
+
/// Property declaration being implemented
ObjCPropertyDecl *PropertyDecl;
@@ -1466,9 +1528,10 @@ private:
ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
Kind PK,
- ObjCIvarDecl *ivarDecl)
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc)
: Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
- PropertyDecl(property), PropertyIvarDecl(ivarDecl),
+ IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
GetterCXXConstructor(0), SetterCXXAssignment(0) {
assert (PK == Dynamic || PropertyIvarDecl);
}
@@ -1478,11 +1541,11 @@ public:
SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
Kind PK,
- ObjCIvarDecl *ivarDecl);
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc);
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtLoc, getLocation());
- }
+ virtual SourceRange getSourceRange() const;
+
SourceLocation getLocStart() const { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
@@ -1498,7 +1561,13 @@ public:
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
- void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; }
+ SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }
+
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
+ SourceLocation IvarLoc) {
+ PropertyIvarDecl = Ivar;
+ this->IvarLoc = IvarLoc;
+ }
Expr *getGetterCXXConstructor() const {
return GetterCXXConstructor;
@@ -1517,6 +1586,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCPropertyImplDecl *D) { return true; }
static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
+
+ friend class ASTDeclReader;
};
} // end namespace clang
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index b532668242fd..176c6badae16 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -53,7 +53,7 @@ class TemplateParameterList {
SourceLocation RAngleLoc);
public:
- static TemplateParameterList *Create(ASTContext &C,
+ static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
NamedDecl **Params,
@@ -85,7 +85,7 @@ public:
return begin()[Idx];
}
- /// \btief Returns the minimum number of arguments needed to form a
+ /// \brief Returns the minimum number of arguments needed to form a
/// template specialization. This may be fewer than the number of
/// template parameters, if some of the parameters have default
/// arguments or if there is a parameter pack.
@@ -107,101 +107,57 @@ public:
}
};
-/// \brief A helper class for making template argument lists.
-class TemplateArgumentListBuilder {
- TemplateArgument *StructuredArgs;
- unsigned MaxStructuredArgs;
- unsigned NumStructuredArgs;
-
- llvm::SmallVector<TemplateArgument, 4> 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),
- MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
- AddingToPack(false), PackBeginIndex(0) { }
-
- void Append(const TemplateArgument &Arg);
- void BeginPack();
- void EndPack();
-
- unsigned flatSize() const { return FlatArgs.size(); }
- const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); }
-
- 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;
- }
-};
-
/// \brief A template argument list.
-///
-/// FIXME: In the future, this class will be extended to support
-/// variadic templates and member templates, which will make some of
-/// the function names below make more sense.
class TemplateArgumentList {
/// \brief The template argument list.
///
/// The integer value will be non-zero to indicate that this
/// template argument list does own the pointer.
- llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
+ llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
/// \brief The number of template arguments in this template
/// argument list.
- unsigned NumFlatArguments;
-
- llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
- unsigned NumStructuredArguments;
+ unsigned NumArguments;
TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL
void operator=(const TemplateArgumentList &Other); // DO NOT IMPL
+
+ TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
+ bool Owned)
+ : Arguments(Args, Owned), NumArguments(NumArgs) { }
+
public:
- /// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs'
- /// it copies them into a locally new[]'d array. If passed "false", then it
- /// just references the array passed in. This is only safe if the builder
- /// outlives it, but saves a copy.
- TemplateArgumentList(ASTContext &Context,
- TemplateArgumentListBuilder &Builder,
- bool TakeArgs);
-
- /// TemplateArgumentList - It copies the template arguments into a locally
- /// new[]'d array.
- TemplateArgumentList(ASTContext &Context,
- const TemplateArgument *Args, unsigned NumArgs);
-
- /// Produces a shallow copy of the given template argument list. This
- /// assumes that the input argument list outlives it. This takes the list as
- /// a pointer to avoid looking like a copy constructor, since this really
- /// really isn't safe to use that way.
- explicit TemplateArgumentList(const TemplateArgumentList *Other);
-
- TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { }
-
- /// \brief Copies the template arguments into a locally new[]'d array.
- void init(ASTContext &Context,
- const TemplateArgument *Args, unsigned NumArgs);
+ /// \brief Type used to indicate that the template argument list itself is a
+ /// stack object. It does not own its template arguments.
+ enum OnStackType { OnStack };
+
+ /// \brief Create a new template argument list that copies the given set of
+ /// template arguments.
+ static TemplateArgumentList *CreateCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Construct a new, temporary template argument list on the stack.
+ ///
+ /// The template argument list does not own the template arguments
+ /// provided.
+ explicit TemplateArgumentList(OnStackType,
+ const TemplateArgument *Args, unsigned NumArgs)
+ : Arguments(Args, false), NumArguments(NumArgs) { }
+
+ /// \brief Produces a shallow copy of the given template argument list.
+ ///
+ /// This operation assumes that the input argument list outlives it.
+ /// This takes the list as a pointer to avoid looking like a copy
+ /// constructor, since this really really isn't safe to use that
+ /// way.
+ explicit TemplateArgumentList(const TemplateArgumentList *Other)
+ : Arguments(Other->data(), false), NumArguments(Other->size()) { }
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
- assert(Idx < NumFlatArguments && "Invalid template argument index");
- return getFlatArgumentList()[Idx];
+ assert(Idx < NumArguments && "Invalid template argument index");
+ return data()[Idx];
}
/// \brief Retrieve the template argument at a given index.
@@ -209,15 +165,11 @@ public:
/// \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; }
+ unsigned size() const { return NumArguments; }
- /// \brief Retrieve the flattened template argument list.
- const TemplateArgument *getFlatArgumentList() const {
- return FlatArguments.getPointer();
+ /// \brief Retrieve a pointer to the template argument list.
+ const TemplateArgument *data() const {
+ return Arguments.getPointer();
}
};
@@ -292,7 +244,31 @@ public:
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
+ FunctionTemplateSpecializationInfo(FunctionDecl *FD,
+ FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI)
+ : Function(FD),
+ Template(Template, TSK - 1),
+ TemplateArguments(TemplateArgs),
+ TemplateArgumentsAsWritten(TemplateArgsAsWritten),
+ PointOfInstantiation(POI) { }
+
public:
+ static FunctionTemplateSpecializationInfo *
+ Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI) {
+ return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
+ TemplateArgs,
+ TemplateArgsAsWritten,
+ POI);
+ }
+
/// \brief The function template specialization that this structure
/// describes.
FunctionDecl *Function;
@@ -345,8 +321,8 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, TemplateArguments->getFlatArgumentList(),
- TemplateArguments->flat_size(),
+ Profile(ID, TemplateArguments->data(),
+ TemplateArguments->size(),
Function->getASTContext());
}
@@ -441,11 +417,6 @@ class DependentFunctionTemplateSpecializationInfo {
return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
}
- const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc*>(
- &getTemplates()[getNumTemplates()]);
- }
-
public:
DependentFunctionTemplateSpecializationInfo(
const UnresolvedSetImpl &Templates,
@@ -463,6 +434,12 @@ public:
return getTemplates()[I];
}
+ /// \brief Returns the explicit template arguments that were given.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc*>(
+ &getTemplates()[getNumTemplates()]);
+ }
+
/// \brief Returns the number of explicit template arguments that were given.
unsigned getNumTemplateArgs() const {
return d.NumArgs;
@@ -584,7 +561,7 @@ protected:
/// for the common pointer.
CommonBase *getCommonPtr();
- virtual CommonBase *newCommon() = 0;
+ virtual CommonBase *newCommon(ASTContext &C) = 0;
// Construct a template decl with name, parameters, and templated element.
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
@@ -789,19 +766,13 @@ protected:
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
- CommonBase *newCommon();
+ CommonBase *newCommon(ASTContext &C);
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
- friend void FunctionDecl::setFunctionTemplateSpecialization(
- FunctionTemplateDecl *Template,
- const TemplateArgumentList *TemplateArgs,
- void *InsertPos,
- TemplateSpecializationKind TSK,
- const TemplateArgumentListInfo *TemplateArgsAsWritten,
- SourceLocation PointOfInstantiation);
+ friend class FunctionDecl;
/// \brief Retrieve the set of function template specializations of this
/// function template.
@@ -940,15 +911,15 @@ class TemplateTypeParmDecl : public TypeDecl {
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
- TypeForDecl = Type.getTypePtr();
+ TypeForDecl = Type.getTypePtrOrNull();
}
public:
- static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
+ static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
- static TemplateTypeParmDecl *Create(ASTContext &C, EmptyShell Empty);
+ static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty);
/// \brief Whether this template type parameter was declared with
/// the 'typename' keyword. If not, it was declared with the 'class'
@@ -1014,22 +985,54 @@ public:
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl
- : public VarDecl, protected TemplateParmPosition {
+ : public DeclaratorDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
+ // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
+ // down here to save memory.
+
+ /// \brief Whether this non-type template parameter is a parameter pack.
+ bool ParameterPack;
+
+ /// \brief Whether this non-type template parameter is an "expanded"
+ /// parameter pack, meaning that its type is a pack expansion and we
+ /// already know the set of types that expansion expands to.
+ bool ExpandedParameterPack;
+
+ /// \brief The number of types in an expanded parameter pack.
+ unsigned NumExpandedTypes;
+
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
- TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
+ bool ParameterPack, TypeSourceInfo *TInfo)
+ : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
+ TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+ ParameterPack(ParameterPack), ExpandedParameterPack(false),
+ NumExpandedTypes(0)
{ }
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes,
+ unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
+
+ friend class ASTDeclReader;
+
public:
static NonTypeTemplateParmDecl *
- Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo);
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack,
+ TypeSourceInfo *TInfo);
+
+ static NonTypeTemplateParmDecl *
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes, unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth;
@@ -1037,6 +1040,9 @@ public:
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;
+ SourceLocation getInnerLocStart() const;
+ SourceRange getSourceRange() const;
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
@@ -1071,6 +1077,65 @@ public:
DefaultArgumentAndInherited.setInt(false);
}
+ /// \brief Whether this parameter is a non-type template parameter pack.
+ ///
+ /// If the parameter is a parameter pack, the type may be a
+ /// \c PackExpansionType. In the following example, the \c Dims parameter
+ /// is a parameter pack (whose type is 'unsigned').
+ ///
+ /// \code
+ /// template<typename T, unsigned ...Dims> struct multi_array;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
+ /// \brief Whether this parameter is a non-type template parameter pack
+ /// that has different types at different positions.
+ ///
+ /// A parameter pack is an expanded parameter pack when the original
+ /// parameter pack's type was itself a pack expansion, and that expansion
+ /// has already been expanded. For example, given:
+ ///
+ /// \code
+ /// template<typename ...Types>
+ /// struct X {
+ /// template<Types ...Values>
+ /// struct Y { /* ... */ };
+ /// };
+ /// \endcode
+ ///
+ /// The parameter pack \c Values has a \c PackExpansionType as its type,
+ /// which expands \c Types. When \c Types is supplied with template arguments
+ /// by instantiating \c X, the instantiation of \c Values becomes an
+ /// expanded parameter pack. For example, instantiating
+ /// \c X<int, unsigned int> results in \c Values being an expanded parameter
+ /// pack with expansion types \c int and \c unsigned int.
+ ///
+ /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions
+ /// return the expansion types.
+ bool isExpandedParameterPack() const { return ExpandedParameterPack; }
+
+ /// \brief Retrieves the number of expansion types in an expanded parameter pack.
+ unsigned getNumExpansionTypes() const {
+ assert(ExpandedParameterPack && "Not an expansion parameter pack");
+ return NumExpandedTypes;
+ }
+
+ /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// pack.
+ QualType getExpansionType(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
+ }
+
+ /// \brief Retrieve a particular expansion type source info within an
+ /// expanded parameter pack.
+ TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
@@ -1092,24 +1157,36 @@ class TemplateTemplateParmDecl
/// Whether or not the default argument was inherited.
bool DefaultArgumentWasInherited;
+ /// \brief Whether this parameter is a parameter pack.
+ bool ParameterPack;
+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
- unsigned D, unsigned P,
+ unsigned D, unsigned P, bool ParameterPack,
IdentifierInfo *Id, TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
TemplateParmPosition(D, P), DefaultArgument(),
- DefaultArgumentWasInherited(false)
+ DefaultArgumentWasInherited(false), ParameterPack(ParameterPack)
{ }
public:
- static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
+ static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id,
+ unsigned P, bool ParameterPack,
+ IdentifierInfo *Id,
TemplateParameterList *Params);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
+ /// \brief Whether this template template parameter is a template
+ /// parameter pack.
+ ///
+ /// \code
+ /// template<template <class T> ...MetaFunctions> struct Apply;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
@@ -1211,7 +1288,7 @@ class ClassTemplateSpecializationDecl
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList TemplateArgs;
+ TemplateArgumentList *TemplateArgs;
/// \brief The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
@@ -1224,7 +1301,8 @@ protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation L,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl);
explicit ClassTemplateSpecializationDecl(Kind DK);
@@ -1233,7 +1311,8 @@ public:
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl);
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
@@ -1259,15 +1338,7 @@ public:
/// \brief Retrieve the template arguments of the class template
/// specialization.
const TemplateArgumentList &getTemplateArgs() const {
- return TemplateArgs;
- }
-
- /// \brief Initialize the template arguments of the class template
- /// specialization.
- void initTemplateArgs(TemplateArgument *Args, unsigned NumArgs) {
- assert(TemplateArgs.flat_size() == 0 &&
- "Template arguments already initialized!");
- TemplateArgs.init(getASTContext(), Args, NumArgs);
+ return *TemplateArgs;
}
/// \brief Determine the kind of specialization that this
@@ -1357,18 +1428,6 @@ public:
SpecializedTemplate = PS;
}
- /// \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,
- TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- ASTContext &Ctx = getASTContext();
- setInstantiationOf(PartialSpec,
- new (Ctx) TemplateArgumentList(Ctx, TemplateArgs,
- NumTemplateArgs));
- }
-
/// \brief Note that this class template specialization is an instantiation
/// of the given class template.
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
@@ -1415,8 +1474,7 @@ public:
SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(),
- getASTContext());
+ Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
}
static void
@@ -1440,6 +1498,9 @@ public:
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
return true;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
class ClassTemplatePartialSpecializationDecl
@@ -1469,15 +1530,16 @@ class ClassTemplatePartialSpecializationDecl
DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
TemplateArgumentLoc *ArgInfos,
unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl,
unsigned SequenceNumber)
: ClassTemplateSpecializationDecl(Context,
ClassTemplatePartialSpecialization,
- TK, DC, L, SpecializedTemplate, Builder,
- PrevDecl),
+ TK, DC, L, SpecializedTemplate,
+ Args, NumArgs, PrevDecl),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
InstantiatedFromMember(0, false) { }
@@ -1493,7 +1555,8 @@ public:
Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
const TemplateArgumentListInfo &ArgInfos,
QualType CanonInjectedType,
ClassTemplatePartialSpecializationDecl *PrevDecl,
@@ -1512,18 +1575,11 @@ public:
return TemplateParams;
}
- void initTemplateParameters(TemplateParameterList *Params) {
- assert(TemplateParams == 0 && "TemplateParams already set");
- TemplateParams = Params;
- }
-
/// Get the template arguments as written.
TemplateArgumentLoc *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
}
- void initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos);
-
/// Get the number of template arguments as written.
unsigned getNumTemplateArgsAsWritten() const {
return NumArgsAsWritten;
@@ -1532,8 +1588,7 @@ public:
/// \brief Get the sequence number for this class template partial
/// specialization.
unsigned getSequenceNumber() const { return SequenceNumber; }
- void setSequenceNumber(unsigned N) { SequenceNumber = N; }
-
+
/// \brief Retrieve the member class template partial specialization from
/// which this particular class template partial specialization was
/// instantiated.
@@ -1617,6 +1672,9 @@ public:
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
return true;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// Declaration of a class template.
@@ -1630,6 +1688,8 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common : CommonBase {
+ Common() : LazySpecializations() { }
+
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@@ -1641,25 +1701,31 @@ protected:
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
+
+ /// \brief If non-null, points to an array of specializations (including
+ /// partial specializations) known ownly by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations/
+ /// partial specializations that follow.
+ uint32_t *LazySpecializations;
};
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations();
+
/// \brief Retrieve the set of specializations of this class template.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
- return getCommonPtr()->Specializations;
- }
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations();
/// \brief Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
- getPartialSpecializations() {
- return getCommonPtr()->PartialSpecializations;
- }
+ getPartialSpecializations();
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
- CommonBase *newCommon();
+ CommonBase *newCommon(ASTContext &C);
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -1693,9 +1759,7 @@ public:
/// \brief Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
- void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
- getSpecializations().InsertNode(D, InsertPos);
- }
+ void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
ClassTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl();
@@ -1729,9 +1793,7 @@ public:
/// \brief Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
- void *InsertPos) {
- getPartialSpecializations().InsertNode(D, InsertPos);
- }
+ void *InsertPos);
/// \brief Return the next partial specialization sequence number.
unsigned getNextPartialSpecSequenceNumber() {
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 8bb627597520..e54719b33d30 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -315,7 +315,7 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
/// retrieved using its member functions (e.g.,
/// getCXXConstructorName).
class DeclarationNameTable {
- ASTContext &Ctx;
+ const ASTContext &Ctx;
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
CXXOperatorIdName *CXXOperatorNames; // Operator names
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
@@ -324,7 +324,7 @@ class DeclarationNameTable {
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
public:
- DeclarationNameTable(ASTContext &C);
+ DeclarationNameTable(const ASTContext &C);
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
@@ -402,7 +402,7 @@ struct DeclarationNameLoc {
DeclarationNameLoc(DeclarationName Name);
// FIXME: this should go away once all DNLocs are properly initialized.
- DeclarationNameLoc() { NamedType.TInfo = 0; }
+ DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
}; // struct DeclarationNameLoc
@@ -492,6 +492,10 @@ public:
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
}
+ /// \brief Determine whether this name contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
/// getAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
new file mode 100644
index 000000000000..035f57c12ea7
--- /dev/null
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -0,0 +1,82 @@
+//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- 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 EvaluatedExprVisitor class template, which visits
+// the potentially-evaluated subexpressions of a potentially-evaluated
+// expression.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+
+namespace clang {
+
+class ASTContext;
+
+/// \begin Given a potentially-evaluated expression, this visitor visits all
+/// of its potentially-evaluated subexpressions, recursively.
+template<typename ImplClass>
+class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
+ ASTContext &Context;
+
+public:
+ explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
+
+ // Expressions that have no potentially-evaluated subexpressions (but may have
+ // other sub-expressions).
+ void VisitDeclRefExpr(DeclRefExpr *E) { }
+ void VisitOffsetOfExpr(OffsetOfExpr *E) { }
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { }
+ void VisitBlockExpr(BlockExpr *E) { }
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
+ void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
+
+ void VisitMemberExpr(MemberExpr *E) {
+ // Only the base matters.
+ return this->Visit(E->getBase());
+ }
+
+ void VisitChooseExpr(ChooseExpr *E) {
+ // Only the selected subexpression matters; the other one is not evaluated.
+ return this->Visit(E->getChosenSubExpr(Context));
+ }
+
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ // Only the actual initializer matters; the designators are all constant
+ // expressions.
+ return this->Visit(E->getInit());
+ }
+
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ // typeid(expression) is potentially evaluated when the argument is
+ // a glvalue of polymorphic type. (C++ 5.2.8p2-3)
+ if (!E->isTypeOperand() && E->Classify(Context).isGLValue())
+ if (const RecordType *Record
+ = E->getExprOperand()->getType()->template getAs<RecordType>())
+ if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic())
+ return this->Visit(E->getExprOperand());
+ }
+
+ /// \brief The basis case walks all of the children of the statement or
+ /// expression, assuming they are all potentially evaluated.
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_range C = S->children(); C; ++C)
+ if (*C)
+ this->Visit(*C);
+ }
+};
+
+}
+
+#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 48130becf3b5..a17205c2b6b9 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -25,6 +25,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include <cctype>
#include <vector>
namespace clang {
@@ -39,8 +40,10 @@ namespace clang {
class CXXBaseSpecifier;
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
+ class ObjCPropertyRefExpr;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
+ class OpaqueValueExpr;
/// \brief A simple array of base specifiers.
typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
@@ -52,24 +55,14 @@ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
class Expr : public Stmt {
QualType TR;
- virtual void ANCHOR(); // key function.
protected:
- /// TypeDependent - Whether this expression is type-dependent
- /// (C++ [temp.dep.expr]).
- bool TypeDependent : 1;
-
- /// ValueDependent - Whether this expression is value-dependent
- /// (C++ [temp.dep.constexpr]).
- bool ValueDependent : 1;
-
- /// ValueKind - The value classification of this expression.
- /// Only actually used by certain subclasses.
- unsigned ValueKind : 2;
-
- enum { BitsRemaining = 28 };
-
- Expr(StmtClass SC, QualType T, bool TD, bool VD)
- : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) {
+ Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD, bool ContainsUnexpandedParameterPack) : Stmt(SC) {
+ ExprBits.TypeDependent = TD;
+ ExprBits.ValueDependent = VD;
+ ExprBits.ValueKind = VK;
+ ExprBits.ObjectKind = OK;
+ ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
setType(T);
}
@@ -77,15 +70,6 @@ protected:
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
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) {
// In C++, the type of an expression is always adjusted so that it
@@ -108,10 +92,10 @@ public:
/// @code
/// template<int Size, char (&Chars)[Size]> struct meta_string;
/// @endcode
- bool isValueDependent() const { return ValueDependent; }
+ bool isValueDependent() const { return ExprBits.ValueDependent; }
/// \brief Set whether this expression is value-dependent or not.
- void setValueDependent(bool VD) { ValueDependent = VD; }
+ void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; }
/// isTypeDependent - Determines whether this expression is
/// type-dependent (C++ [temp.dep.expr]), which means that its type
@@ -124,19 +108,38 @@ public:
/// x + y;
/// }
/// @endcode
- bool isTypeDependent() const { return TypeDependent; }
+ bool isTypeDependent() const { return ExprBits.TypeDependent; }
/// \brief Set whether this expression is type-dependent or not.
- void setTypeDependent(bool TD) { TypeDependent = TD; }
+ void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; }
+
+ /// \brief Whether this expression contains an unexpanded parameter
+ /// pack (for C++0x variadic templates).
+ ///
+ /// Given the following function template:
+ ///
+ /// \code
+ /// template<typename F, typename ...Types>
+ /// void forward(const F &f, Types &&...args) {
+ /// f(static_cast<Types&&>(args)...);
+ /// }
+ /// \endcode
+ ///
+ /// The expressions \c args and \c static_cast<Types&&>(args) both
+ /// contain parameter packs.
+ bool containsUnexpandedParameterPack() const {
+ return ExprBits.ContainsUnexpandedParameterPack;
+ }
- /// 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.
- virtual SourceRange getSourceRange() const = 0;
+ /// \brief Set the bit that describes whether this expression
+ /// contains an unexpanded parameter pack.
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ ExprBits.ContainsUnexpandedParameterPack = PP;
+ }
/// getExprLoc - Return the preferred location for the arrow when diagnosing
/// a problem with a generic expression.
- virtual SourceLocation getExprLoc() const { return getLocStart(); }
+ SourceLocation getExprLoc() const;
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in Loc and Ranges
@@ -145,19 +148,25 @@ public:
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
SourceRange &R2, ASTContext &Ctx) 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
- /// - e[i]
- /// - (e), where e must be an lvalue
- /// - e.name, where e must be an lvalue
- /// - e->name
- /// - *e, the type of e cannot be a function type
- /// - string-constant
- /// - reference type [C++ [expr]]
- /// - b ? x : y, where x and y are lvalues of suitable types [C++]
+ /// isLValue - True if this expression is an "l-value" according to
+ /// the rules of the current language. C and C++ give somewhat
+ /// different rules for this concept, but in general, the result of
+ /// an l-value expression identifies a specific object whereas the
+ /// result of an r-value expression is a value detached from any
+ /// specific storage.
///
- enum isLvalueResult {
+ /// C++0x divides the concept of "r-value" into pure r-values
+ /// ("pr-values") and so-called expiring values ("x-values"), which
+ /// identify specific objects that can be safely cannibalized for
+ /// their resources. This is an unfortunate abuse of terminology on
+ /// the part of the C++ committee. In Clang, when we say "r-value",
+ /// we generally mean a pr-value.
+ bool isLValue() const { return getValueKind() == VK_LValue; }
+ bool isRValue() const { return getValueKind() == VK_RValue; }
+ bool isXValue() const { return getValueKind() == VK_XValue; }
+ bool isGLValue() const { return getValueKind() != VK_RValue; }
+
+ enum LValueClassification {
LV_Valid,
LV_NotObjectType,
LV_IncompleteVoidType,
@@ -167,7 +176,8 @@ public:
LV_SubObjCPropertySetting,
LV_ClassTemporary
};
- isLvalueResult isLvalue(ASTContext &Ctx) const;
+ /// Reasons why an expression might not be an l-value.
+ LValueClassification ClassifyLValue(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,
@@ -252,8 +262,14 @@ public:
bool isPRValue() const { return Kind >= CL_Function; }
bool isRValue() const { return Kind >= CL_XValue; }
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
+
+ /// \brief Create a simple, modifiably lvalue
+ static Classification makeSimpleLValue() {
+ return Classification(CL_LValue, CM_Modifiable);
+ }
+
};
- /// \brief classify - Classify this expression according to the C++0x
+ /// \brief Classify - Classify this expression according to the C++0x
/// expression taxonomy.
///
/// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the
@@ -269,7 +285,7 @@ public:
return ClassifyImpl(Ctx, 0);
}
- /// \brief classifyModifiable - Classify this expression according to the
+ /// \brief ClassifyModifiable - Classify this expression according to the
/// C++0x expression taxonomy, and see if it is valid on the left side
/// of an assignment.
///
@@ -281,6 +297,40 @@ public:
return ClassifyImpl(Ctx, &Loc);
}
+ /// getValueKindForType - Given a formal return or parameter type,
+ /// give its value kind.
+ static ExprValueKind getValueKindForType(QualType T) {
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ return (isa<LValueReferenceType>(RT)
+ ? VK_LValue
+ : (RT->getPointeeType()->isFunctionType()
+ ? VK_LValue : VK_XValue));
+ return VK_RValue;
+ }
+
+ /// getValueKind - The value kind that this expression produces.
+ ExprValueKind getValueKind() const {
+ return static_cast<ExprValueKind>(ExprBits.ValueKind);
+ }
+
+ /// getObjectKind - The object kind that this expression produces.
+ /// Object kinds are meaningful only for expressions that yield an
+ /// l-value or x-value.
+ ExprObjectKind getObjectKind() const {
+ return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
+ }
+
+ bool isOrdinaryOrBitFieldObject() const {
+ ExprObjectKind OK = getObjectKind();
+ return (OK == OK_Ordinary || OK == OK_BitField);
+ }
+
+ /// setValueKind - Set the value kind produced by this expression.
+ void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
+
+ /// setObjectKind - Set the object kind produced by this expression.
+ void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }
+
private:
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
@@ -294,6 +344,10 @@ public:
return const_cast<Expr*>(this)->getBitField();
}
+ /// \brief If this expression is an l-value for an Objective C
+ /// property, find the underlying property reference expression.
+ const ObjCPropertyRefExpr *getObjCProperty() const;
+
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
@@ -355,33 +409,49 @@ public:
/// any crazy technique (that has nothing to do with language standards) that
/// we want to. If this function returns true, it returns the folded constant
/// in Result.
- bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
+ bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we we can fold and convert to a boolean condition using
/// any crazy technique that we want to.
- bool EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const;
+ bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
- bool isEvaluatable(ASTContext &Ctx) const;
+ bool isEvaluatable(const ASTContext &Ctx) const;
/// HasSideEffects - This routine returns true for all those expressions
- /// which must be evaluated each time and must not be optimization away
+ /// which must be evaluated each time and must not be optimized away
/// or evaluated at compile time. Example is a function call, volatile
/// variable read.
- bool HasSideEffects(ASTContext &Ctx) const;
+ bool HasSideEffects(const ASTContext &Ctx) const;
/// EvaluateAsInt - Call Evaluate and return the folded integer. This
/// must be called on an expression that constant folds to an integer.
- llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
+ llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue
/// with link time known address.
- bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const;
+ bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue.
- bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const;
+ bool EvaluateAsAnyLValue(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// \brief Enumeration used to describe the kind of Null pointer constant
+ /// returned from \c isNullPointerConstant().
+ enum NullPointerConstantKind {
+ /// \brief Expression is not a Null pointer constant.
+ NPCK_NotNull = 0,
+
+ /// \brief Expression is a Null pointer constant built from a zero integer.
+ NPCK_ZeroInteger,
+
+ /// \brief Expression is a C++0X nullptr.
+ NPCK_CXX0X_nullptr,
+
+ /// \brief Expression is a GNU-style __null constant.
+ NPCK_GNUNull
+ };
/// \brief Enumeration used to describe how \c isNullPointerConstant()
/// should cope with value-dependent expressions.
@@ -398,16 +468,30 @@ public:
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,
- NullPointerConstantValueDependence NPC) const;
+ /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
+ /// a Null pointer constant. The return value can further distinguish the
+ /// kind of NULL pointer constant that was detected.
+ NullPointerConstantKind isNullPointerConstant(
+ ASTContext &Ctx,
+ NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
+ /// \brief Returns true if this expression is a bound member function.
+ bool isBoundMemberFunction(ASTContext &Ctx) const;
+
+ /// \brief Result type of CanThrow().
+ enum CanThrowResult {
+ CT_Cannot,
+ CT_Dependent,
+ CT_Can
+ };
+ /// \brief Test if this expression, if evaluated, might throw, according to
+ /// the rules of C++ [expr.unary.noexcept].
+ CanThrowResult CanThrow(ASTContext &C) const;
+
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
/// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
@@ -422,6 +506,18 @@ public:
/// ParenExpr or ImplicitCastExprs, returning their operand.
Expr *IgnoreParenImpCasts();
+ const Expr *IgnoreParenImpCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenImpCasts();
+ }
+
+ /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
+ /// CastExprs that represent lvalue casts, returning their operand.
+ Expr *IgnoreParenLValueCasts();
+
+ const Expr *IgnoreParenLValueCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
+ }
+
/// 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.
@@ -436,14 +532,9 @@ public:
/// the expression is a default argument.
bool isDefaultArgument() const;
- /// \brief Determine whether this expression directly creates a
- /// temporary object (of class type).
- bool isTemporaryObject() const { return getTemporaryObject() != 0; }
-
- /// \brief If this expression directly creates a temporary object of
- /// class type, return the expression that actually constructs that
- /// temporary object.
- const Expr *getTemporaryObject() const;
+ /// \brief Determine whether the result of this expression is a
+ /// temporary object of the given class type.
+ bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
const Expr *IgnoreParens() const {
return const_cast<Expr*>(this)->IgnoreParens();
@@ -470,6 +561,63 @@ public:
// Primary Expressions.
//===----------------------------------------------------------------------===//
+/// OpaqueValueExpr - An expression referring to an opaque object of a
+/// fixed type and value class. These don't correspond to concrete
+/// syntax; instead they're used to express operations (usually copy
+/// operations) on values whose source is generally obvious from
+/// context.
+class OpaqueValueExpr : public Expr {
+ friend class ASTStmtReader;
+ Expr *SourceExpr;
+ SourceLocation Loc;
+
+public:
+ OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
+ ExprObjectKind OK = OK_Ordinary)
+ : Expr(OpaqueValueExprClass, T, VK, OK,
+ T->isDependentType(), T->isDependentType(), false),
+ SourceExpr(0), Loc(Loc) {
+ }
+
+ /// Given an expression which invokes a copy constructor --- i.e. a
+ /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
+ /// find the OpaqueValueExpr that's the source of the construction.
+ static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
+
+ explicit OpaqueValueExpr(EmptyShell Empty)
+ : Expr(OpaqueValueExprClass, Empty) { }
+
+ /// \brief Retrieve the location of this expression.
+ SourceLocation getLocation() const { return Loc; }
+
+ SourceRange getSourceRange() const {
+ if (SourceExpr) return SourceExpr->getSourceRange();
+ return Loc;
+ }
+ SourceLocation getExprLoc() const {
+ if (SourceExpr) return SourceExpr->getExprLoc();
+ return Loc;
+ }
+
+ child_range children() { return child_range(); }
+
+ /// The source expression of an opaque value expression is the
+ /// expression which originally generated the value. This is
+ /// provided as a convenience for analyses that don't wish to
+ /// precisely model the execution behavior of the program.
+ ///
+ /// The source expression is typically set when building the
+ /// expression which binds the opaque value expression in the first
+ /// place.
+ Expr *getSourceExpr() const { return SourceExpr; }
+ void setSourceExpr(Expr *e) { SourceExpr = e; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpaqueValueExprClass;
+ }
+ static bool classof(const OpaqueValueExpr *) { return true; }
+};
+
/// \brief Represents the qualifier that may precede a C++ name, e.g., the
/// "std::" in "std::sort".
struct NameQualifier {
@@ -505,6 +653,8 @@ struct ExplicitTemplateArgumentList {
}
void initializeFrom(const TemplateArgumentListInfo &List);
+ void initializeFrom(const TemplateArgumentListInfo &List,
+ bool &Dependent, bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
static std::size_t sizeFor(const TemplateArgumentListInfo &List);
@@ -551,12 +701,12 @@ class DeclRefExpr : public Expr {
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
ValueDecl *D, SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs,
- QualType T);
+ QualType T, ExprValueKind VK);
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
ValueDecl *D, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
- QualType T);
+ QualType T, ExprValueKind VK);
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
@@ -567,8 +717,9 @@ class DeclRefExpr : public Expr {
void computeDependence();
public:
- DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) :
- Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) {
+ DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) :
+ Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false),
+ DecoratedD(d, 0), Loc(l) {
computeDependence();
}
@@ -577,7 +728,7 @@ public:
SourceRange QualifierRange,
ValueDecl *D,
SourceLocation NameLoc,
- QualType T,
+ QualType T, ExprValueKind VK,
const TemplateArgumentListInfo *TemplateArgs = 0);
static DeclRefExpr *Create(ASTContext &Context,
@@ -585,12 +736,14 @@ public:
SourceRange QualifierRange,
ValueDecl *D,
const DeclarationNameInfo &NameInfo,
- QualType T,
+ QualType T, ExprValueKind VK,
const TemplateArgumentListInfo *TemplateArgs = 0);
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(ASTContext &Context,
- bool HasQualifier, unsigned NumTemplateArgs);
+ bool HasQualifier,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
ValueDecl *getDecl() { return DecoratedD.getPointer(); }
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
@@ -602,7 +755,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
/// \brief Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
@@ -706,8 +859,7 @@ public:
static bool classof(const DeclRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -730,8 +882,10 @@ private:
IdentType Type;
public:
PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
- : Expr(PredefinedExprClass, type, type->isDependentType(),
- type->isDependentType()), Loc(l), Type(IT) {}
+ : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
+ type->isDependentType(), type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(l), Type(IT) {}
/// \brief Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
@@ -745,7 +899,7 @@ public:
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == PredefinedExprClass;
@@ -753,8 +907,7 @@ public:
static bool classof(const PredefinedExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
@@ -817,7 +970,9 @@ public:
// or UnsignedLongLongTy
IntegerLiteral(ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, false, false), Loc(l) {
+ : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
setValue(C, V);
}
@@ -829,7 +984,7 @@ public:
static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
llvm::APInt getValue() const { return Num.getValue(); }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
@@ -843,8 +998,7 @@ public:
static bool classof(const IntegerLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
class CharacterLiteral : public Expr {
@@ -854,8 +1008,9 @@ class CharacterLiteral : public Expr {
public:
// type should be IntTy
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
- : Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l),
- IsWide(iswide) {
+ : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(value), Loc(l), IsWide(iswide) {
}
/// \brief Construct an empty character literal.
@@ -864,7 +1019,7 @@ public:
SourceLocation getLocation() const { return Loc; }
bool isWide() const { return IsWide; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
unsigned getValue() const { return Value; }
@@ -878,8 +1033,7 @@ public:
static bool classof(const CharacterLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
class FloatingLiteral : public Expr {
@@ -889,7 +1043,8 @@ class FloatingLiteral : public Expr {
FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, false, false),
+ : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
+ false),
IsExact(isexact), Loc(L) {
setValue(C, V);
}
@@ -919,7 +1074,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FloatingLiteralClass;
@@ -927,8 +1082,7 @@ public:
static bool classof(const FloatingLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
@@ -940,7 +1094,9 @@ class ImaginaryLiteral : public Expr {
Stmt *Val;
public:
ImaginaryLiteral(Expr *val, QualType Ty)
- : Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {}
+ : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Val(val) {}
/// \brief Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
@@ -950,15 +1106,14 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- virtual SourceRange getSourceRange() const { return Val->getSourceRange(); }
+ SourceRange getSourceRange() const { return Val->getSourceRange(); }
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();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
@@ -984,7 +1139,8 @@ class StringLiteral : public Expr {
unsigned NumConcatenated;
SourceLocation TokLocs[1];
- StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {}
+ StringLiteral(QualType Ty) :
+ Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false) {}
public:
/// This is the "fully general" constructor that allows representation of
@@ -1034,12 +1190,23 @@ public:
assert(TokNum < NumConcatenated && "Invalid tok number");
TokLocs[TokNum] = L;
}
+
+ /// getLocationOfByte - Return a source location that points to the specified
+ /// byte of this string literal.
+ ///
+ /// Strings are amazingly complex. They can be formed from multiple tokens
+ /// and can have escape sequences in them in addition to the usual trigraph
+ /// and escaped newline business. This routine handles this complexity.
+ ///
+ SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features,
+ const TargetInfo &Target) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
}
static bool classof(const Stmt *T) {
@@ -1048,8 +1215,7 @@ public:
static bool classof(const StringLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
@@ -1060,7 +1226,9 @@ class ParenExpr : public Expr {
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(),
- val->isTypeDependent(), val->isValueDependent()),
+ val->getValueKind(), val->getObjectKind(),
+ val->isTypeDependent(), val->isValueDependent(),
+ val->containsUnexpandedParameterPack()),
L(l), R(r), Val(val) {}
/// \brief Construct an empty parenthesized expression.
@@ -1071,7 +1239,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- virtual SourceRange getSourceRange() const { return SourceRange(L, R); }
+ SourceRange getSourceRange() const { return SourceRange(L, R); }
/// \brief Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
@@ -1087,8 +1255,7 @@ public:
static bool classof(const ParenExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
@@ -1112,10 +1279,12 @@ private:
Stmt *Val;
public:
- UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
- : Expr(UnaryOperatorClass, type,
+ UnaryOperator(Expr *input, Opcode opc, QualType type,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
+ : Expr(UnaryOperatorClass, type, VK, OK,
input->isTypeDependent() || type->isDependentType(),
- input->isValueDependent()),
+ input->isValueDependent(),
+ input->containsUnexpandedParameterPack()),
Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
@@ -1137,7 +1306,7 @@ public:
return Op == UO_PostInc || Op == UO_PostDec;
}
- /// isPostfix - Return true if this is a prefix operation, like --x.
+ /// isPrefix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
return Op == UO_PreInc || Op == UO_PreDec;
}
@@ -1167,13 +1336,13 @@ public:
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (isPostfix())
return SourceRange(Val->getLocStart(), Loc);
else
return SourceRange(Loc, Val->getLocEnd());
}
- virtual SourceLocation getExprLoc() const { return Loc; }
+ SourceLocation getExprLoc() const { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
@@ -1181,8 +1350,7 @@ public:
static bool classof(const UnaryOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
@@ -1369,7 +1537,7 @@ public:
return NumExprs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(OperatorLoc, RParenLoc);
}
@@ -1380,8 +1548,12 @@ public:
static bool classof(const OffsetOfExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin =
+ reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
+ + NumComps);
+ return child_range(begin, begin + NumExprs);
+ }
};
/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
@@ -1399,10 +1571,11 @@ public:
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
- Expr(SizeOfAlignOfExprClass, resultType,
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- TInfo->getType()->isDependentType()),
+ TInfo->getType()->isDependentType(),
+ TInfo->getType()->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
Argument.Ty = TInfo;
}
@@ -1410,10 +1583,11 @@ public:
SizeOfAlignOfExpr(bool issizeof, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
- Expr(SizeOfAlignOfExprClass, resultType,
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- E->isTypeDependent()),
+ E->isTypeDependent(),
+ E->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
Argument.Ex = E;
}
@@ -1459,7 +1633,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(OpLoc, RParenLoc);
}
@@ -1469,8 +1643,7 @@ public:
static bool classof(const SizeOfAlignOfExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children();
};
//===----------------------------------------------------------------------===//
@@ -1484,10 +1657,13 @@ class ArraySubscriptExpr : public Expr {
SourceLocation RBracketLoc;
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation rbracketloc)
- : Expr(ArraySubscriptExprClass, t,
+ : Expr(ArraySubscriptExprClass, t, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
RBracketLoc(rbracketloc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -1530,14 +1706,14 @@ public:
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
- virtual SourceRange getSourceRange() const {
+ 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(); }
+ SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ArraySubscriptExprClass;
@@ -1545,8 +1721,9 @@ public:
static bool classof(const ArraySubscriptExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
@@ -1557,19 +1734,36 @@ public:
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
- enum { FN=0, ARGS_START=1 };
+ enum { FN=0, PREARGS_START=1 };
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);
+ // These versions of the constructor are for derived classes.
+ CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
+ Expr **args, unsigned numargs, QualType t, ExprValueKind VK,
+ SourceLocation rparenloc);
+ CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty);
+
+ Stmt *getPreArg(unsigned i) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ const Stmt *getPreArg(unsigned i) const {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ void setPreArg(unsigned i, Stmt *PreArg) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ SubExprs[PREARGS_START+i] = PreArg;
+ }
+
+ unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
- SourceLocation rparenloc);
+ ExprValueKind VK, SourceLocation rparenloc);
/// \brief Build an empty call expression.
CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
@@ -1593,20 +1787,25 @@ public:
///
unsigned getNumArgs() const { return NumArgs; }
+ /// \brief Retrieve the call arguments.
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
+ }
+
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_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;
+ SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
}
/// setNumArgs - This changes the number of arguments present in this call.
@@ -1617,10 +1816,16 @@ public:
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();}
+ arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
+ arg_iterator arg_end() {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
+ const_arg_iterator arg_begin() const {
+ return SubExprs+PREARGS_START+getNumPreArgs();
+ }
+ const_arg_iterator arg_end() const {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
@@ -1628,7 +1833,7 @@ public:
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
- unsigned isBuiltinCall(ASTContext &Context) const;
+ unsigned isBuiltinCall(const 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
@@ -1638,7 +1843,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getCallee()->getLocStart(), RParenLoc);
}
@@ -1649,8 +1854,10 @@ public:
static bool classof(const CallExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
+ }
};
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
@@ -1705,9 +1912,11 @@ class MemberExpr : public Expr {
public:
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- const DeclarationNameInfo &NameInfo, QualType ty)
- : Expr(MemberExprClass, ty,
- base->isTypeDependent(), base->isValueDependent()),
+ const DeclarationNameInfo &NameInfo, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
@@ -1719,9 +1928,11 @@ public:
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion oeprators).
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- SourceLocation l, QualType ty)
- : Expr(MemberExprClass, ty,
- base->isTypeDependent(), base->isValueDependent()),
+ SourceLocation l, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
@@ -1731,7 +1942,7 @@ public:
ValueDecl *memberdecl, DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs,
- QualType ty);
+ QualType ty, ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -1866,7 +2077,7 @@ public:
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
@@ -1878,7 +2089,7 @@ public:
return SourceRange(BaseLoc, EndLoc);
}
- virtual SourceLocation getExprLoc() const { return MemberLoc; }
+ SourceLocation getExprLoc() const { return MemberLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
@@ -1886,8 +2097,10 @@ public:
static bool classof(const MemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
+
+ friend class ASTReader;
+ friend class ASTStmtWriter;
};
/// CompoundLiteralExpr - [C99 6.5.2.5]
@@ -1904,11 +2117,12 @@ class CompoundLiteralExpr : public Expr {
Stmt *Init;
bool FileScope;
public:
- // FIXME: Can compound literals be value-dependent?
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
- QualType T, Expr *init, bool fileScope)
- : Expr(CompoundLiteralExprClass, T,
- tinfo->getType()->isDependentType(), false),
+ QualType T, ExprValueKind VK, Expr *init, bool fileScope)
+ : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
+ tinfo->getType()->isDependentType(),
+ init->isValueDependent(),
+ init->containsUnexpandedParameterPack()),
LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {}
/// \brief Construct an empty compound literal.
@@ -1928,7 +2142,7 @@ public:
TypeSourceInfo *getTypeSourceInfo() const { return TInfo; }
void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// FIXME: Init should never be null.
if (!Init)
return SourceRange();
@@ -1943,8 +2157,7 @@ public:
static bool classof(const CompoundLiteralExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Init, &Init+1); }
};
/// CastExpr - Base class for type casts, including both implicit
@@ -1956,11 +2169,9 @@ public:
typedef clang::CastKind CastKind;
private:
- unsigned Kind : 5;
- unsigned BasePathSize : BitsRemaining - 5;
Stmt *Op;
- void CheckBasePath() const {
+ void CheckCastConsistency() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBase:
@@ -1972,16 +2183,13 @@ private:
break;
// These should not have an inheritance path.
- case CK_Unknown:
case CK_BitCast:
- case CK_LValueBitCast:
- case CK_NoOp:
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
- case CK_UserDefinedConversion:
+ case CK_NullToPointer:
case CK_ConstructorConversion:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
@@ -1991,10 +2199,32 @@ private:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
- case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+ // fallthrough to check for null base path
+
+ case CK_Dependent:
+ case CK_LValueToRValue:
+ case CK_GetObjCProperty:
+ case CK_NoOp:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_FloatingToBoolean:
+ case CK_MemberPointerToBoolean:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean:
+ case CK_LValueBitCast: // -> bool&
+ case CK_UserDefinedConversion: // operator bool()
assert(path_empty() && "Cast kind should not have a base path!");
break;
}
@@ -2007,26 +2237,33 @@ private:
CXXBaseSpecifier **path_buffer();
protected:
- CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op,
- unsigned BasePathSize) :
- Expr(SC, ty,
+ CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ const CastKind kind, Expr *op, unsigned BasePathSize) :
+ Expr(SC, ty, VK, OK_Ordinary,
// 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())),
- Kind(kind), BasePathSize(BasePathSize), Op(op) {
- CheckBasePath();
+ ty->isDependentType() || (op && op->isValueDependent()),
+ (ty->containsUnexpandedParameterPack() ||
+ op->containsUnexpandedParameterPack())),
+ Op(op) {
+ assert(kind != CK_Invalid && "creating cast with invalid cast kind");
+ CastExprBits.Kind = kind;
+ CastExprBits.BasePathSize = BasePathSize;
+ CheckCastConsistency();
}
/// \brief Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
- : Expr(SC, Empty), BasePathSize(BasePathSize) { }
+ : Expr(SC, Empty) {
+ CastExprBits.BasePathSize = BasePathSize;
+ }
public:
- CastKind getCastKind() const { return static_cast<CastKind>(Kind); }
- void setCastKind(CastKind K) { Kind = K; }
+ CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
+ void setCastKind(CastKind K) { CastExprBits.Kind = K; }
const char *getCastKindName() const;
Expr *getSubExpr() { return cast<Expr>(Op); }
@@ -2043,8 +2280,8 @@ public:
typedef CXXBaseSpecifier **path_iterator;
typedef const CXXBaseSpecifier * const *path_const_iterator;
- bool path_empty() const { return BasePathSize == 0; }
- unsigned path_size() const { return BasePathSize; }
+ bool path_empty() const { return CastExprBits.BasePathSize == 0; }
+ unsigned path_size() const { return CastExprBits.BasePathSize; }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
@@ -2059,8 +2296,7 @@ public:
static bool classof(const CastExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Op, &Op+1); }
};
/// ImplicitCastExpr - Allows us to explicitly represent implicit type
@@ -2087,8 +2323,7 @@ class ImplicitCastExpr : public CastExpr {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) {
- ValueKind = VK;
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
}
/// \brief Construct an empty implicit cast.
@@ -2099,8 +2334,7 @@ public:
enum OnStack_t { OnStack };
ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
ExprValueKind VK)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) {
- ValueKind = VK;
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
@@ -2110,18 +2344,10 @@ public:
static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return getSubExpr()->getSourceRange();
}
- /// getValueKind - The value kind that this cast produces.
- ExprValueKind getValueKind() const {
- return static_cast<ExprValueKind>(ValueKind);
- }
-
- /// setValueKind - Set the value kind this cast produces.
- void setValueKind(ExprValueKind Cat) { ValueKind = Cat; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
@@ -2150,9 +2376,10 @@ class ExplicitCastExpr : public CastExpr {
TypeSourceInfo *TInfo;
protected:
- ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy)
- : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {}
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
@@ -2182,10 +2409,10 @@ class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
- CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
+ CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
- : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize,
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
@@ -2193,7 +2420,8 @@ class CStyleCastExpr : public ExplicitCastExpr {
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
public:
- static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K,
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K,
Expr *Op, const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation R);
@@ -2206,7 +2434,7 @@ public:
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
@@ -2246,10 +2474,13 @@ private:
public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc)
- : Expr(BinaryOperatorClass, ResTy,
+ : Expr(BinaryOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -2272,7 +2503,7 @@ public:
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
}
@@ -2291,6 +2522,7 @@ public:
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
/// predicates to categorize the respective opcodes.
+ bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
@@ -2312,13 +2544,24 @@ public:
static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
- bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; }
- bool isCompoundAssignmentOp() const {
+ static bool isAssignmentOp(Opcode Opc) {
+ return Opc >= BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }
+
+ static bool isCompoundAssignmentOp(Opcode Opc) {
return Opc > BO_Assign && Opc <= BO_OrAssign;
}
- bool isShiftAssignOp() const {
+ bool isCompoundAssignmentOp() const {
+ return isCompoundAssignmentOp(getOpcode());
+ }
+
+ static bool isShiftAssignOp(Opcode Opc) {
return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
}
+ bool isShiftAssignOp() const {
+ return isShiftAssignOp(getOpcode());
+ }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
@@ -2327,15 +2570,19 @@ public:
static bool classof(const BinaryOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
protected:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc, bool dead)
- : Expr(CompoundAssignOperatorClass, ResTy,
+ : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -2355,11 +2602,11 @@ class CompoundAssignOperator : public BinaryOperator {
QualType ComputationLHSType;
QualType ComputationResultType;
public:
- CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc,
- QualType ResType, QualType CompLHSType,
- QualType CompResultType,
+ CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
+ ExprValueKind VK, ExprObjectKind OK,
+ QualType CompLHSType, QualType CompResultType,
SourceLocation OpLoc)
- : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true),
+ : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),
ComputationLHSType(CompLHSType),
ComputationResultType(CompResultType) {
assert(isCompoundAssignmentOp() &&
@@ -2385,75 +2632,97 @@ public:
}
};
-/// ConditionalOperator - The ?: operator. Note that LHS may be null when the
-/// GNU "missing LHS" extension is in use.
-///
-class ConditionalOperator : public Expr {
+/// AbstractConditionalOperator - An abstract base class for
+/// ConditionalOperator and BinaryConditionalOperator.
+class AbstractConditionalOperator : public Expr {
+ SourceLocation QuestionLoc, ColonLoc;
+ friend class ASTStmtReader;
+
+protected:
+ AbstractConditionalOperator(StmtClass SC, QualType T,
+ ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD,
+ bool ContainsUnexpandedParameterPack,
+ SourceLocation qloc,
+ SourceLocation cloc)
+ : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack),
+ QuestionLoc(qloc), ColonLoc(cloc) {}
+
+ AbstractConditionalOperator(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) { }
+
+public:
+ // getCond - Return the expression representing the condition for
+ // the ?: operator.
+ Expr *getCond() const;
+
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const;
+
+ // getFalseExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to false. This is
+ // the same as getRHS.
+ Expr *getFalseExpr() const;
+
+ SourceLocation getQuestionLoc() const { return QuestionLoc; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass ||
+ T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const AbstractConditionalOperator *) { return true; }
+};
+
+/// ConditionalOperator - The ?: ternary operator. The GNU "missing
+/// middle" extension is a BinaryConditionalOperator.
+class ConditionalOperator : public AbstractConditionalOperator {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
- Stmt* Save;
- SourceLocation QuestionLoc, ColonLoc;
+
+ friend class ASTStmtReader;
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
- SourceLocation CLoc, Expr *rhs, Expr *save, QualType t)
- : Expr(ConditionalOperatorClass, t,
+ SourceLocation CLoc, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
// 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() ||
- (lhs && lhs->isValueDependent()) ||
- (rhs && rhs->isValueDependent()))),
- QuestionLoc(QLoc),
- ColonLoc(CLoc) {
+ (lhs->isTypeDependent() || rhs->isTypeDependent()),
+ (cond->isValueDependent() || lhs->isValueDependent() ||
+ rhs->isValueDependent()),
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ QLoc, CLoc) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
- Save = save;
}
/// \brief Build an empty conditional operator.
explicit ConditionalOperator(EmptyShell Empty)
- : Expr(ConditionalOperatorClass, Empty) { }
+ : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
// getCond - Return the expression representing the condition for
- // the ?: operator.
+ // the ?: operator.
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
- void setCond(Expr *E) { SubExprs[COND] = E; }
- // getTrueExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to true.
- Expr *getTrueExpr() const {
- return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]);
- }
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }
- // getFalseExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to false. This is the same as getRHS.
+ // getFalseExpr - 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]); }
- // getSaveExpr - In most cases this value will be null. Except a GCC extension
- // allows the left subexpression to be omitted, and instead of that condition
- // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the
- // expression "x" is only evaluated once. Under this senario, this function
- // returns the original, non-converted condition expression for the ?:operator
- Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; }
-
- Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); }
- void setLHS(Expr *E) { SubExprs[LHS] = E; }
-
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
- void setRHS(Expr *E) { SubExprs[RHS] = E; }
-
- Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; }
- void setSAVE(Expr *E) { Save = 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 {
+ SourceRange getSourceRange() const {
return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -2462,18 +2731,118 @@ public:
static bool classof(const ConditionalOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// BinaryConditionalOperator - The GNU extension to the conditional
+/// operator which allows the middle operand to be omitted.
+///
+/// This is a different expression kind on the assumption that almost
+/// every client ends up needing to know that these are different.
+class BinaryConditionalOperator : public AbstractConditionalOperator {
+ enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS };
+
+ /// - the common condition/left-hand-side expression, which will be
+ /// evaluated as the opaque value
+ /// - the condition, expressed in terms of the opaque value
+ /// - the left-hand-side, expressed in terms of the opaque value
+ /// - the right-hand-side
+ Stmt *SubExprs[NUM_SUBEXPRS];
+ OpaqueValueExpr *OpaqueValue;
+
+ friend class ASTStmtReader;
+public:
+ BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue,
+ Expr *cond, Expr *lhs, Expr *rhs,
+ SourceLocation qloc, SourceLocation cloc,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK,
+ (common->isTypeDependent() || rhs->isTypeDependent()),
+ (common->isValueDependent() || rhs->isValueDependent()),
+ (common->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ qloc, cloc),
+ OpaqueValue(opaqueValue) {
+ SubExprs[COMMON] = common;
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+
+ OpaqueValue->setSourceExpr(common);
+ }
+
+ /// \brief Build an empty conditional operator.
+ explicit BinaryConditionalOperator(EmptyShell Empty)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }
+
+ /// \brief getCommon - Return the common expression, written to the
+ /// left of the condition. The opaque value will be bound to the
+ /// result of this expression.
+ Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }
+
+ /// \brief getOpaqueValue - Return the opaque value placeholder.
+ OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
+
+ /// \brief getCond - Return the condition expression; this is defined
+ /// in terms of the opaque value.
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+
+ /// \brief getTrueExpr - Return the subexpression which will be
+ /// evaluated if the condition evaluates to true; this is defined
+ /// in terms of the opaque value.
+ Expr *getTrueExpr() const {
+ return cast<Expr>(SubExprs[LHS]);
+ }
+
+ /// \brief getFalseExpr - Return the subexpression which will be
+ /// evaluated if the condnition evaluates to false; this is
+ /// defined in terms of the opaque value.
+ Expr *getFalseExpr() const {
+ return cast<Expr>(SubExprs[RHS]);
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const BinaryConditionalOperator *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
+ }
};
+inline Expr *AbstractConditionalOperator::getCond() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getCond();
+ return cast<BinaryConditionalOperator>(this)->getCond();
+}
+
+inline Expr *AbstractConditionalOperator::getTrueExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getTrueExpr();
+ return cast<BinaryConditionalOperator>(this)->getTrueExpr();
+}
+
+inline Expr *AbstractConditionalOperator::getFalseExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getFalseExpr();
+ return cast<BinaryConditionalOperator>(this)->getFalseExpr();
+}
+
/// AddrLabelExpr - The GNU address of label extension, representing &&label.
class AddrLabelExpr : public Expr {
SourceLocation AmpAmpLoc, LabelLoc;
- LabelStmt *Label;
+ LabelDecl *Label;
public:
- AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
+ AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
QualType t)
- : Expr(AddrLabelExprClass, t, false, false),
+ : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false),
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
/// \brief Build an empty address of a label expression.
@@ -2485,12 +2854,12 @@ public:
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AmpAmpLoc, LabelLoc);
}
- LabelStmt *getLabel() const { return Label; }
- void setLabel(LabelStmt *S) { Label = S; }
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *L) { Label = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AddrLabelExprClass;
@@ -2498,13 +2867,15 @@ public:
static bool classof(const AddrLabelExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
/// takes the value of the last subexpression.
+///
+/// A StmtExpr is always an r-value; values "returned" out of a
+/// StmtExpr will be copied.
class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
@@ -2512,7 +2883,8 @@ public:
// FIXME: Does type-dependence need to be computed differently?
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
- Expr(StmtExprClass, T, T->isDependentType(), false),
+ Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
+ T->isDependentType(), false, false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
/// \brief Build an empty statement expression.
@@ -2522,7 +2894,7 @@ public:
const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
void setSubStmt(CompoundStmt *S) { SubStmt = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LParenLoc, RParenLoc);
}
@@ -2537,55 +2909,9 @@ public:
static bool classof(const StmtExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
-/// TypesCompatibleExpr - GNU builtin-in function __builtin_types_compatible_p.
-/// This AST node represents a function that returns 1 if two *types* (not
-/// expressions) are compatible. The result of this built-in function can be
-/// used in integer constant expressions.
-class TypesCompatibleExpr : public Expr {
- TypeSourceInfo *TInfo1;
- TypeSourceInfo *TInfo2;
- SourceLocation BuiltinLoc, RParenLoc;
-public:
- TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
- TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2,
- SourceLocation RP) :
- Expr(TypesCompatibleExprClass, ReturnType, false, false),
- TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {}
-
- /// \brief Build an empty __builtin_type_compatible_p expression.
- explicit TypesCompatibleExpr(EmptyShell Empty)
- : Expr(TypesCompatibleExprClass, Empty) { }
-
- TypeSourceInfo *getArgTInfo1() const { return TInfo1; }
- void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; }
- TypeSourceInfo *getArgTInfo2() const { return TInfo2; }
- void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; }
-
- QualType getArgType1() const { return TInfo1->getType(); }
- QualType getArgType2() const { return TInfo2->getType(); }
-
- 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;
- }
- static bool classof(const TypesCompatibleExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
/// ShuffleVectorExpr - clang-specific builtin-in function
/// __builtin_shufflevector.
@@ -2604,18 +2930,9 @@ class ShuffleVectorExpr : public Expr {
unsigned NumExprs;
public:
- // FIXME: Can a shufflevector be value-dependent? Does type-dependence need
- // to be computed differently?
ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
QualType Type, SourceLocation BLoc,
- SourceLocation RP) :
- Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false),
- BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) {
-
- SubExprs = new (C) Stmt*[nexpr];
- for (unsigned i = 0; i < nexpr; i++)
- SubExprs[i] = args[i];
- }
+ SourceLocation RP);
/// \brief Build an empty vector-shuffle expression.
explicit ShuffleVectorExpr(EmptyShell Empty)
@@ -2627,7 +2944,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2640,6 +2957,9 @@ public:
/// pointers.
unsigned getNumSubExprs() const { return NumExprs; }
+ /// \brief Retrieve the array of expressions.
+ Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
+
/// getExpr - Return the Expr at the specified index.
Expr *getExpr(unsigned Index) {
assert((Index < NumExprs) && "Arg access out of range!");
@@ -2658,8 +2978,9 @@ public:
}
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
+ }
};
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
@@ -2676,9 +2997,13 @@ class ChooseExpr : public Expr {
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
SourceLocation BuiltinLoc, RParenLoc;
public:
- ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
+ ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK,
SourceLocation RP, bool TypeDependent, bool ValueDependent)
- : Expr(ChooseExprClass, t, TypeDependent, ValueDependent),
+ : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
BuiltinLoc(BLoc), RParenLoc(RP) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
@@ -2690,11 +3015,11 @@ public:
/// isConditionTrue - Return whether the condition is true (i.e. not
/// equal to zero).
- bool isConditionTrue(ASTContext &C) const;
+ bool isConditionTrue(const ASTContext &C) const;
/// getChosenSubExpr - Return the subexpression chosen according to the
/// condition.
- Expr *getChosenSubExpr(ASTContext &C) const {
+ Expr *getChosenSubExpr(const ASTContext &C) const {
return isConditionTrue(C) ? getLHS() : getRHS();
}
@@ -2711,7 +3036,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2720,8 +3045,9 @@ public:
static bool classof(const ChooseExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// GNUNullExpr - Implements the GNU __null extension, which is a name
@@ -2736,7 +3062,8 @@ class GNUNullExpr : public Expr {
public:
GNUNullExpr(QualType Ty, SourceLocation Loc)
- : Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { }
+ : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false),
+ TokenLoc(Loc) { }
/// \brief Build an empty GNU __null expression.
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
@@ -2745,7 +3072,7 @@ public:
SourceLocation getTokenLocation() const { return TokenLoc; }
void setTokenLocation(SourceLocation L) { TokenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TokenLoc);
}
static bool classof(const Stmt *T) {
@@ -2754,8 +3081,7 @@ public:
static bool classof(const GNUNullExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// VAArgExpr, used for the builtin function __builtin_va_arg.
@@ -2766,7 +3092,10 @@ class VAArgExpr : public Expr {
public:
VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
SourceLocation RPLoc, QualType t)
- : Expr(VAArgExprClass, t, t->isDependentType(), false),
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
+ t->isDependentType(), false,
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
Val(e), TInfo(TInfo),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
@@ -2787,7 +3116,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2796,8 +3125,7 @@ public:
static bool classof(const VAArgExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// @brief Describes an C or C++ initializer list.
@@ -2866,12 +3194,15 @@ public:
unsigned getNumInits() const { return InitExprs.size(); }
- const Expr* getInit(unsigned Init) const {
+ /// \brief Retrieve the set of initializers.
+ Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+
+ 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]);
}
@@ -2933,17 +3264,18 @@ public:
HadArrayRangeDesignator = ARD;
}
- virtual SourceRange getSourceRange() const {
- return SourceRange(LBraceLoc, RBraceLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == InitListExprClass;
}
static bool classof(const InitListExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (InitExprs.empty()) return child_range();
+ return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
+ }
typedef InitExprsTy::iterator iterator;
typedef InitExprsTy::const_iterator const_iterator;
@@ -3182,6 +3514,15 @@ public:
return Designators + NumDesignators;
}
+ typedef std::reverse_iterator<designators_iterator>
+ reverse_designators_iterator;
+ reverse_designators_iterator designators_rbegin() {
+ return reverse_designators_iterator(designators_end());
+ }
+ reverse_designators_iterator designators_rend() {
+ return reverse_designators_iterator(designators_begin());
+ }
+
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
void setDesignators(ASTContext &C, const Designator *Desigs,
@@ -3235,7 +3576,7 @@ public:
void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
const Designator *Last);
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitExprClass;
@@ -3243,8 +3584,10 @@ public:
static bool classof(const DesignatedInitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
+ return child_range(begin, begin + NumSubExprs);
+ }
};
/// \brief Represents an implicitly-generated value initialization of
@@ -3258,7 +3601,8 @@ public:
class ImplicitValueInitExpr : public Expr {
public:
explicit ImplicitValueInitExpr(QualType ty)
- : Expr(ImplicitValueInitExprClass, ty, false, false) { }
+ : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, false, false) { }
/// \brief Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
@@ -3269,13 +3613,12 @@ public:
}
static bool classof(const ImplicitValueInitExpr *) { return true; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange();
}
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
@@ -3308,7 +3651,7 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LParenLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -3317,8 +3660,9 @@ public:
static bool classof(const ParenListExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0]+NumExprs);
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -3342,10 +3686,12 @@ class ExtVectorElementExpr : public Expr {
IdentifierInfo *Accessor;
SourceLocation AccessorLoc;
public:
- ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
- SourceLocation loc)
- : Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(),
- base->isValueDependent()),
+ ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
+ IdentifierInfo &accessor, SourceLocation loc)
+ : Expr(ExtVectorElementExprClass, ty, VK,
+ (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent),
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
/// \brief Build an empty vector element expression.
@@ -3373,7 +3719,7 @@ public:
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), AccessorLoc);
}
@@ -3387,8 +3733,7 @@ public:
static bool classof(const ExtVectorElementExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
@@ -3397,11 +3742,11 @@ public:
class BlockExpr : public Expr {
protected:
BlockDecl *TheBlock;
- bool HasBlockDeclRefExprs;
public:
- BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs)
- : Expr(BlockExprClass, ty, ty->isDependentType(), false),
- TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {}
+ BlockExpr(BlockDecl *BD, QualType ty)
+ : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
+ ty->isDependentType(), false, false),
+ TheBlock(BD) {}
/// \brief Build an empty block expression.
explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
@@ -3415,58 +3760,46 @@ public:
const Stmt *getBody() const;
Stmt *getBody();
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getCaretLocation(), getBody()->getLocEnd());
}
/// getFunctionType - Return the underlying function type for this block.
const FunctionType *getFunctionType() const;
- /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr
- /// inside of the block that reference values outside the block.
- bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; }
- void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; }
-
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();
+ child_range children() { return child_range(); }
};
-/// BlockDeclRefExpr - A reference to a declared variable, function,
-/// enum, etc.
+/// BlockDeclRefExpr - A reference to a local variable declared in an
+/// enclosing scope.
class BlockDeclRefExpr : public Expr {
- ValueDecl *D;
+ VarDecl *D;
SourceLocation Loc;
bool IsByRef : 1;
bool ConstQualAdded : 1;
- Stmt *CopyConstructorVal;
public:
- // FIXME: Fix type/value dependence!
- BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
- bool constAdded = false,
- Stmt *copyConstructorVal = 0)
- : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false),
- D(d), Loc(l), IsByRef(ByRef),
- ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) {}
+ BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
+ SourceLocation l, bool ByRef, bool constAdded = false);
// \brief Build an empty reference to a declared variable in a
// block.
explicit BlockDeclRefExpr(EmptyShell Empty)
: Expr(BlockDeclRefExprClass, Empty) { }
- ValueDecl *getDecl() { return D; }
- const ValueDecl *getDecl() const { return D; }
- void setDecl(ValueDecl *VD) { D = VD; }
+ VarDecl *getDecl() { return D; }
+ const VarDecl *getDecl() const { return D; }
+ void setDecl(VarDecl *VD) { D = VD; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
bool isByRef() const { return IsByRef; }
void setByRef(bool BR) { IsByRef = BR; }
@@ -3474,20 +3807,13 @@ public:
bool isConstQualAdded() const { return ConstQualAdded; }
void setConstQualAdded(bool C) { ConstQualAdded = C; }
- const Expr *getCopyConstructorExpr() const
- { return cast_or_null<Expr>(CopyConstructorVal); }
- Expr *getCopyConstructorExpr()
- { return cast_or_null<Expr>(CopyConstructorVal); }
- void setCopyConstructorExpr(Expr *E) { CopyConstructorVal = E; }
-
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();
+ child_range children() { return child_range(); }
};
} // end namespace clang
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 0a9435479d93..85ce9621d928 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -21,11 +21,11 @@
namespace clang {
- class CXXConstructorDecl;
- class CXXDestructorDecl;
- class CXXMethodDecl;
- class CXXTemporary;
- class TemplateArgumentListInfo;
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXTemporary;
+class TemplateArgumentListInfo;
//===--------------------------------------------------------------------===//
// C++ Expressions.
@@ -51,8 +51,9 @@ class CXXOperatorCallExpr : public CallExpr {
public:
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
Expr **args, unsigned numargs, QualType t,
- SourceLocation operatorloc)
- : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc),
+ ExprValueKind VK, SourceLocation operatorloc)
+ : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK,
+ operatorloc),
Operator(Op) {}
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
CallExpr(C, CXXOperatorCallExprClass, Empty) { }
@@ -70,7 +71,7 @@ public:
/// bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXOperatorCallExprClass;
@@ -89,8 +90,8 @@ public:
class CXXMemberCallExpr : public CallExpr {
public:
CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs,
- QualType t, SourceLocation rparenloc)
- : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {}
+ QualType t, ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, numargs, t, VK, RP) {}
CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
: CallExpr(C, CXXMemberCallExprClass, Empty) { }
@@ -100,7 +101,14 @@ public:
/// operation would return "x".
Expr *getImplicitObjectArgument();
- virtual SourceRange getSourceRange() const;
+ /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of
+ /// the implicit object argument. Note that this is may not be the same
+ /// declaration as that of the class context of the CXXMethodDecl which this
+ /// function is calling.
+ /// FIXME: Returns 0 for member pointer call exprs.
+ CXXRecordDecl *getRecordDecl();
+
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
@@ -108,6 +116,35 @@ public:
static bool classof(const CXXMemberCallExpr *) { return true; }
};
+/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function.
+class CUDAKernelCallExpr : public CallExpr {
+private:
+ enum { CONFIG, END_PREARG };
+
+public:
+ CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config,
+ Expr **args, unsigned numargs, QualType t,
+ ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, numargs, t, VK,
+ RP) {
+ setConfig(Config);
+ }
+
+ CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { }
+
+ const CallExpr *getConfig() const {
+ return cast_or_null<CallExpr>(getPreArg(CONFIG));
+ }
+ CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); }
+ void setConfig(CallExpr *E) { setPreArg(CONFIG, E); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CUDAKernelCallExprClass;
+ }
+ static bool classof(const CUDAKernelCallExpr *) { return true; }
+};
+
/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
/// const_cast.
@@ -118,26 +155,33 @@ public:
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
SourceLocation Loc; // the location of the casting op
-
+ SourceLocation RParenLoc; // the location of the right parenthesis
+
protected:
- CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- unsigned PathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
+ CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
+ RParenLoc(RParenLoc) {}
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(SC, Shell, PathSize) { }
+ friend class ASTStmtReader;
+
public:
const char *getCastName() const;
/// \brief Retrieve the location of the cast operator keyword, e.g.,
/// "static_cast".
SourceLocation getOperatorLoc() const { return Loc; }
- void setOperatorLoc(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
+ /// \brief Retrieve the location of the closing parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParenLoc);
}
static bool classof(const Stmt *T) {
switch (T->getStmtClass()) {
@@ -158,20 +202,21 @@ public:
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
- CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
+ CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
public:
static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
- CastKind K, Expr *Op,
+ ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *Path,
- TypeSourceInfo *Written, SourceLocation L);
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
unsigned PathSize);
@@ -188,20 +233,21 @@ public:
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
- CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
- unsigned pathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
+ Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
public:
static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
- CastKind Kind, Expr *Op,
+ ExprValueKind VK, CastKind Kind, Expr *Op,
const CXXCastPath *Path,
- TypeSourceInfo *Written, SourceLocation L);
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
@@ -219,20 +265,22 @@ public:
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
- CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- unsigned pathSize,
- TypeSourceInfo *writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
+ Expr *op, unsigned pathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
+ pathSize, writtenTy, l, RParenLoc) {}
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
public:
static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
- CastKind Kind, Expr *Op,
- const CXXCastPath *Path,
- TypeSourceInfo *WrittenTy, SourceLocation L);
+ ExprValueKind VK, CastKind Kind,
+ Expr *Op, const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
@@ -248,17 +296,20 @@ public:
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
- CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
- 0, writtenTy, l) {}
+ CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
+ 0, writtenTy, l, RParenLoc) {}
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
public:
- static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
- TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) {
@@ -274,7 +325,9 @@ class CXXBoolLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
- Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {}
+ Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(val), Loc(l) {}
explicit CXXBoolLiteralExpr(EmptyShell Empty)
: Expr(CXXBoolLiteralExprClass, Empty) { }
@@ -282,7 +335,7 @@ public:
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -293,8 +346,7 @@ public:
static bool classof(const CXXBoolLiteralExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
@@ -302,12 +354,14 @@ class CXXNullPtrLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
- Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {}
+ Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {}
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
: Expr(CXXNullPtrLiteralExprClass, Empty) { }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -317,8 +371,7 @@ public:
}
static bool classof(const CXXNullPtrLiteralExpr *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
@@ -333,19 +386,21 @@ private:
public:
CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty,
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
false,
// typeid is value-dependent if the type or expression are dependent
- Operand->getType()->isDependentType()),
+ Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty,
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
- false,
+ false,
// typeid is value-dependent if the type or expression are dependent
- Operand->isTypeDependent() || Operand->isValueDependent()),
+ Operand->isTypeDependent() || Operand->isValueDependent(),
+ Operand->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXTypeidExpr(EmptyShell Empty, bool isExpr)
@@ -383,7 +438,7 @@ public:
Operand = E;
}
- virtual SourceRange getSourceRange() const { return Range; }
+ SourceRange getSourceRange() const { return Range; }
void setSourceRange(SourceRange R) { Range = R; }
static bool classof(const Stmt *T) {
@@ -392,8 +447,84 @@ public:
static bool classof(const CXXTypeidExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
+/// the _GUID that corresponds to the supplied type or expression.
+///
+/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
+class CXXUuidofExpr : public Expr {
+private:
+ llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
+ SourceRange Range;
+
+public:
+ CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->isTypeDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXUuidofExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)0;
+ else
+ Operand = (TypeSourceInfo*)0;
+ }
+
+ bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
+
+ /// \brief Retrieves the type operand of this __uuidof() expression after
+ /// various required adjustments (removing reference types, cv-qualifiers).
+ QualType getTypeOperand() const;
+
+ /// \brief Retrieve source information for the type operand.
+ TypeSourceInfo *getTypeOperandSourceInfo() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ return Operand.get<TypeSourceInfo *>();
+ }
+
+ void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ Operand = TSI;
+ }
+
+ Expr *getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ return static_cast<Expr*>(Operand.get<Stmt *>());
+ }
+
+ void setExprOperand(Expr *E) {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ Operand = E;
+ }
+
+ SourceRange getSourceRange() const { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUuidofExprClass;
+ }
+ static bool classof(const CXXUuidofExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
};
/// CXXThisExpr - Represents the "this" expression in C++, which is a
@@ -413,10 +544,11 @@ class CXXThisExpr : public Expr {
public:
CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
- : Expr(CXXThisExprClass, Type,
+ : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
- Type->isDependentType(), Type->isDependentType()),
+ Type->isDependentType(), Type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
Loc(L), Implicit(isImplicit) { }
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
@@ -424,7 +556,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
bool isImplicit() const { return Implicit; }
void setImplicit(bool I) { Implicit = I; }
@@ -435,8 +567,7 @@ public:
static bool classof(const CXXThisExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
@@ -451,7 +582,9 @@ public:
// exepression. The l is the location of the throw keyword. expr
// can by null, if the optional expression to throw isn't present.
CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) :
- Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {}
+ Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ expr && expr->containsUnexpandedParameterPack()),
+ Op(expr), ThrowLoc(l) {}
CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
@@ -461,7 +594,7 @@ public:
SourceLocation getThrowLoc() const { return ThrowLoc; }
void setThrowLoc(SourceLocation L) { ThrowLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (getSubExpr() == 0)
return SourceRange(ThrowLoc, ThrowLoc);
return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd());
@@ -473,8 +606,9 @@ public:
static bool classof(const CXXThrowExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Op, Op ? &Op+1 : &Op);
+ }
};
/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
@@ -497,12 +631,16 @@ class CXXDefaultArgExpr : public Expr {
param->hasUnparsedDefaultArg()
? param->getType().getNonReferenceType()
: param->getDefaultArg()->getType(),
- false, false),
+ param->getDefaultArg()->getValueKind(),
+ param->getDefaultArg()->getObjectKind(), false, false, false),
Param(param, false), Loc(Loc) { }
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
Expr *SubExpr)
- : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) {
+ : Expr(SC, SubExpr->getType(),
+ SubExpr->getValueKind(), SubExpr->getObjectKind(),
+ false, false, false),
+ Param(param, true), Loc(Loc) {
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}
@@ -544,7 +682,7 @@ public:
/// used.
SourceLocation getUsedLocation() const { return Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// Default argument expressions have no representation in the
// source, so they have an empty source range.
return SourceRange();
@@ -556,8 +694,7 @@ public:
static bool classof(const CXXDefaultArgExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -597,9 +734,12 @@ class CXXBindTemporaryExpr : public Expr {
Stmt *SubExpr;
- CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
- : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
- Temp(temp), SubExpr(subexpr) { }
+ CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr)
+ : Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
+ VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
+ SubExpr->isValueDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ Temp(temp), SubExpr(SubExpr) { }
public:
CXXBindTemporaryExpr(EmptyShell Empty)
@@ -616,7 +756,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
@@ -627,8 +767,7 @@ public:
static bool classof(const CXXBindTemporaryExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
/// CXXConstructExpr - Represents a call to a C++ constructor.
@@ -644,6 +783,7 @@ private:
CXXConstructorDecl *Constructor;
SourceLocation Loc;
+ SourceRange ParenRange;
bool Elidable : 1;
bool ZeroInitialization : 1;
unsigned ConstructKind : 2;
@@ -656,7 +796,8 @@ protected:
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs,
bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete);
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
@@ -675,7 +816,8 @@ public:
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete);
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
CXXConstructorDecl* getConstructor() const { return Constructor; }
@@ -731,7 +873,8 @@ public:
Args[Arg] = ArgExpr;
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
+ SourceRange getParenRange() const { return ParenRange; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
@@ -740,8 +883,9 @@ public:
static bool classof(const CXXConstructExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Args[0], &Args[0]+NumArgs);
+ }
friend class ASTStmtReader;
};
@@ -753,12 +897,13 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
- CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
+ CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
+ TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
- pathSize, writtenTy),
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
+ castExpr, pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
@@ -766,6 +911,7 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
public:
static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
TypeSourceInfo *Written,
SourceLocation TyBeginLoc,
CastKind Kind, Expr *Op,
@@ -779,7 +925,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -804,24 +950,21 @@ public:
/// };
/// @endcode
class CXXTemporaryObjectExpr : public CXXConstructExpr {
- SourceLocation TyBeginLoc;
- SourceLocation RParenLoc;
+ TypeSourceInfo *Type;
public:
CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
- QualType writtenTy, SourceLocation tyBeginLoc,
+ TypeSourceInfo *Type,
Expr **Args,unsigned NumArgs,
- SourceLocation rParenLoc,
+ SourceRange parenRange,
bool ZeroInitialization = false);
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { }
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- SourceLocation getRParenLoc() const { return RParenLoc; }
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
@@ -835,32 +978,31 @@ public:
/// T, which is a non-class type.
///
class CXXScalarValueInitExpr : public Expr {
- SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
+ TypeSourceInfo *TypeInfo;
+ friend class ASTStmtReader;
+
public:
- CXXScalarValueInitExpr(QualType ty, SourceLocation tyBeginLoc,
- SourceLocation rParenLoc ) :
- Expr(CXXScalarValueInitExprClass, ty, false, false),
- TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+ /// \brief Create an explicitly-written scalar-value initialization
+ /// expression.
+ CXXScalarValueInitExpr(QualType Type,
+ TypeSourceInfo *TypeInfo,
+ SourceLocation rParenLoc ) :
+ Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
+ false, false, false),
+ RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+
explicit CXXScalarValueInitExpr(EmptyShell Shell)
: Expr(CXXScalarValueInitExprClass, Shell) { }
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- SourceLocation getRParenLoc() const { return RParenLoc; }
-
- void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
- void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
- /// @brief Whether this initialization expression was
- /// implicitly-generated.
- bool isImplicit() const {
- return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TypeInfo;
}
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXScalarValueInitExprClass;
@@ -868,8 +1010,7 @@ public:
static bool classof(const CXXScalarValueInitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXNewExpr - A new expression for memory allocation and constructor calls,
@@ -882,8 +1023,11 @@ class CXXNewExpr : public Expr {
bool Initializer : 1;
// Do we allocate an array? If so, the first SubExpr is the size expression.
bool Array : 1;
+ // If this is an array allocation, does the usual deallocation
+ // function for the allocated type want to know the allocated size?
+ bool UsualArrayDeleteWantsSize : 1;
// The number of placement new arguments.
- unsigned NumPlacementArgs : 15;
+ unsigned NumPlacementArgs : 14;
// The number of constructor arguments. This may be 1 even for non-class
// types; use the pseudo copy constructor.
unsigned NumConstructorArgs : 14;
@@ -900,12 +1044,17 @@ class CXXNewExpr : public Expr {
// Must be null for all other types.
CXXConstructorDecl *Constructor;
+ /// \brief The allocated type-source information, as written in the source.
+ TypeSourceInfo *AllocatedTypeInfo;
+
/// \brief If the allocated type was expressed as a parenthesized type-id,
/// the source range covering the parenthesized type-id.
SourceRange TypeIdParens;
SourceLocation StartLoc;
SourceLocation EndLoc;
+ SourceLocation ConstructorLParen;
+ SourceLocation ConstructorRParen;
friend class ASTStmtReader;
public:
@@ -914,8 +1063,11 @@ public:
SourceRange TypeIdParens,
Expr *arraySize, CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
- FunctionDecl *operatorDelete, QualType ty,
- SourceLocation startLoc, SourceLocation endLoc);
+ FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
+ QualType ty, TypeSourceInfo *AllocatedTypeInfo,
+ SourceLocation startLoc, SourceLocation endLoc,
+ SourceLocation constructorLParen,
+ SourceLocation constructorRParen);
explicit CXXNewExpr(EmptyShell Shell)
: Expr(CXXNewExprClass, Shell), SubExprs(0) { }
@@ -927,6 +1079,10 @@ public:
return getType()->getAs<PointerType>()->getPointeeType();
}
+ TypeSourceInfo *getAllocatedTypeSourceInfo() const {
+ return AllocatedTypeInfo;
+ }
+
FunctionDecl *getOperatorNew() const { return OperatorNew; }
void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
@@ -943,6 +1099,10 @@ public:
}
unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ Expr **getPlacementArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array);
+ }
+
Expr *getPlacementArg(unsigned i) {
assert(i < NumPlacementArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + i]);
@@ -956,11 +1116,21 @@ public:
SourceRange getTypeIdParens() const { return TypeIdParens; }
bool isGlobalNew() const { return GlobalNew; }
- void setGlobalNew(bool V) { GlobalNew = V; }
bool hasInitializer() const { return Initializer; }
- void setHasInitializer(bool V) { Initializer = V; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
+
+ Expr **getConstructorArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs);
+ }
+
Expr *getConstructorArg(unsigned i) {
assert(i < NumConstructorArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
@@ -1007,13 +1177,13 @@ public:
const_arg_iterator raw_arg_begin() const { return SubExprs; }
const_arg_iterator raw_arg_end() const { return constructor_arg_end(); }
-
SourceLocation getStartLoc() const { return StartLoc; }
- void setStartLoc(SourceLocation L) { StartLoc = L; }
SourceLocation getEndLoc() const { return EndLoc; }
- void setEndLoc(SourceLocation L) { EndLoc = L; }
-
- virtual SourceRange getSourceRange() const {
+
+ SourceLocation getConstructorLParen() const { return ConstructorLParen; }
+ SourceLocation getConstructorRParen() const { return ConstructorRParen; }
+
+ SourceRange getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
@@ -1023,8 +1193,11 @@ public:
static bool classof(const CXXNewExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0] + Array + getNumPlacementArgs()
+ + getNumConstructorArgs());
+ }
};
/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
@@ -1034,6 +1207,13 @@ class CXXDeleteExpr : public Expr {
bool GlobalDelete : 1;
// Is this the array form of delete, i.e. "delete[]"?
bool ArrayForm : 1;
+ // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
+ // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
+ // will be true).
+ bool ArrayFormAsWritten : 1;
+ // Does the usual deallocation function for the element type require
+ // a size_t argument?
+ bool UsualArrayDeleteWantsSize : 1;
// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
// The pointer expression to be deleted.
@@ -1042,30 +1222,42 @@ class CXXDeleteExpr : public Expr {
SourceLocation Loc;
public:
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
+ bool arrayFormAsWritten, bool usualArrayDeleteWantsSize,
FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
- : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete),
- ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg),
- Loc(loc) { }
+ : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
+ arg->containsUnexpandedParameterPack()),
+ GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { }
explicit CXXDeleteExpr(EmptyShell Shell)
: Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { }
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
-
- void setGlobalDelete(bool V) { GlobalDelete = V; }
- void setArrayForm(bool V) { ArrayForm = V; }
+ bool isArrayFormAsWritten() const { return ArrayFormAsWritten; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter. This can be true even if the actual deallocation
+ /// function that we're using doesn't want a size.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
- void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
- void setArgument(Expr *E) { Argument = E; }
- virtual SourceRange getSourceRange() const {
+ /// \brief Retrieve the type being destroyed. If the type being
+ /// destroyed is a dependent type which may or may not be a pointer,
+ /// return an invalid type.
+ QualType getDestroyedType() const;
+
+ SourceRange getSourceRange() const {
return SourceRange(Loc, Argument->getLocEnd());
}
- void setStartLoc(SourceLocation L) { Loc = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDeleteExprClass;
@@ -1073,8 +1265,9 @@ public:
static bool classof(const CXXDeleteExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Argument, &Argument+1); }
+
+ friend class ASTStmtReader;
};
/// \brief Structure used to store the type being destroyed by a
@@ -1171,21 +1364,7 @@ public:
TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc,
SourceLocation TildeLoc,
- PseudoDestructorTypeStorage DestroyedType)
- : Expr(CXXPseudoDestructorExprClass,
- Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
- false, 0, false,
- false, 0, 0,
- FunctionType::ExtInfo())),
- /*isTypeDependent=*/(Base->isTypeDependent() ||
- (DestroyedType.getTypeSourceInfo() &&
- DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
- /*isValueDependent=*/Base->isValueDependent()),
- Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
- OperatorLoc(OperatorLoc), Qualifier(Qualifier),
- QualifierRange(QualifierRange),
- ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
- DestroyedType(DestroyedType) { }
+ PseudoDestructorTypeStorage DestroyedType);
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
: Expr(CXXPseudoDestructorExprClass, Shell),
@@ -1278,7 +1457,7 @@ public:
DestroyedType = PseudoDestructorTypeStorage(Info);
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXPseudoDestructorExprClass;
@@ -1286,8 +1465,7 @@ public:
static bool classof(const CXXPseudoDestructorExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base + 1); }
};
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
@@ -1296,8 +1474,10 @@ public:
/// __is_pod(int) == true
/// __is_enum(std::string) == false
class UnaryTypeTraitExpr : public Expr {
- /// UTT - The trait.
- UnaryTypeTrait UTT;
+ /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned.
+ unsigned UTT : 31;
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
/// Loc - The location of the type trait keyword.
SourceLocation Loc;
@@ -1305,25 +1485,31 @@ class UnaryTypeTraitExpr : public Expr {
/// RParen - The location of the closing paren.
SourceLocation RParen;
- /// QueriedType - The type we're testing.
- QualType QueriedType;
+ /// The type being queried.
+ TypeSourceInfo *QueriedType;
public:
- UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
+ UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt,
+ TypeSourceInfo *queried, bool value,
SourceLocation rparen, QualType ty)
- : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
- UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
+ : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, queried->getType()->isDependentType(),
+ queried->getType()->containsUnexpandedParameterPack()),
+ UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { }
explicit UnaryTypeTraitExpr(EmptyShell Empty)
- : Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0) { }
+ : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false),
+ QueriedType() { }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+ SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
- UnaryTypeTrait getTrait() const { return UTT; }
+ UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); }
- QualType getQueriedType() const { return QueriedType; }
+ QualType getQueriedType() const { return QueriedType->getType(); }
- bool EvaluateTrait(ASTContext&) const;
+ TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
+
+ bool getValue() const { return Value; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryTypeTraitExprClass;
@@ -1331,8 +1517,74 @@ public:
static bool classof(const UnaryTypeTraitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+};
+
+/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_base_of(Base, Derived) == true
+class BinaryTypeTraitExpr : public Expr {
+ /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
+ unsigned BTT : 8;
+
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// The lhs type being queried.
+ TypeSourceInfo *LhsType;
+
+ /// The rhs type being queried.
+ TypeSourceInfo *RhsType;
+
+public:
+ BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
+ TypeSourceInfo *lhsType, TypeSourceInfo *rhsType,
+ bool value, SourceLocation rparen, QualType ty)
+ : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false,
+ lhsType->getType()->isDependentType() ||
+ rhsType->getType()->isDependentType(),
+ (lhsType->getType()->containsUnexpandedParameterPack() ||
+ rhsType->getType()->containsUnexpandedParameterPack())),
+ BTT(btt), Value(value), Loc(loc), RParen(rparen),
+ LhsType(lhsType), RhsType(rhsType) { }
+
+
+ explicit BinaryTypeTraitExpr(EmptyShell Empty)
+ : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false),
+ LhsType(), RhsType() { }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParen);
+ }
+
+ BinaryTypeTrait getTrait() const {
+ return static_cast<BinaryTypeTrait>(BTT);
+ }
+
+ QualType getLhsType() const { return LhsType->getType(); }
+ QualType getRhsType() const { return RhsType->getType(); }
+
+ TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; }
+ TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; }
+
+ bool getValue() const { assert(!isTypeDependent()); return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryTypeTraitExprClass;
+ }
+ static bool classof(const BinaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
};
@@ -1360,23 +1612,23 @@ protected:
/// True if the name was a template-id.
bool HasExplicitTemplateArgs;
- OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent,
+ OverloadExpr(StmtClass K, ASTContext &C,
NestedNameSpecifier *Qualifier, SourceRange QRange,
const DeclarationNameInfo &NameInfo,
- bool HasTemplateArgs,
- UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End,
+ bool KnownDependent = false,
+ bool KnownContainsUnexpandedParameterPack = false);
OverloadExpr(StmtClass K, EmptyShell Empty)
: Expr(K, Empty), Results(0), NumResults(0),
Qualifier(0), HasExplicitTemplateArgs(false) { }
-public:
- /// Computes whether an unresolved lookup on the given declarations
- /// and optional template arguments is type- and value-dependent.
- static bool ComputeDependence(UnresolvedSetIterator Begin,
- UnresolvedSetIterator End,
- const TemplateArgumentListInfo *Args);
+ void initializeResults(ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+public:
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
@@ -1420,9 +1672,6 @@ public:
return UnresolvedSetIterator(Results + NumResults);
}
- void initializeResults(ASTContext &C,
- UnresolvedSetIterator Begin,UnresolvedSetIterator End);
-
/// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
@@ -1469,6 +1718,9 @@ public:
T->getStmtClass() == UnresolvedMemberExprClass;
}
static bool classof(const OverloadExpr *) { return true; }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// \brief A reference to a name which we were able to look up during
@@ -1498,14 +1750,15 @@ class UnresolvedLookupExpr : public OverloadExpr {
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
- UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent,
+ UnresolvedLookupExpr(ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange,
const DeclarationNameInfo &NameInfo,
- bool RequiresADL, bool Overloaded, bool HasTemplateArgs,
+ bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End)
- : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier,
- QRange, NameInfo, HasTemplateArgs, Begin, End),
+ : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo,
+ TemplateArgs, Begin, End),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{}
@@ -1516,7 +1769,6 @@ class UnresolvedLookupExpr : public OverloadExpr {
public:
static UnresolvedLookupExpr *Create(ASTContext &C,
- bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
@@ -1524,16 +1776,12 @@ public:
bool ADL, bool Overloaded,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
- return new(C) UnresolvedLookupExpr(C,
- Dependent ? C.DependentTy : C.OverloadTy,
- Dependent, NamingClass,
- Qualifier, QualifierRange, NameInfo,
- ADL, Overloaded, false,
- Begin, End);
+ return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier,
+ QualifierRange, NameInfo, ADL,
+ Overloaded, 0, Begin, End);
}
static UnresolvedLookupExpr *Create(ASTContext &C,
- bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
@@ -1544,6 +1792,7 @@ public:
UnresolvedSetIterator End);
static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// True if this declaration should be extended by
@@ -1606,15 +1855,14 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range(getNameInfo().getSourceRange());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
}
- virtual StmtIterator child_begin();
- virtual StmtIterator child_end();
+ child_range children() { return child_range(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedLookupExprClass;
@@ -1655,11 +1903,7 @@ class DependentScopeDeclRefExpr : public Expr {
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
const DeclarationNameInfo &NameInfo,
- bool HasExplicitTemplateArgs)
- : Expr(DependentScopeDeclRefExprClass, T, true, true),
- NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
- HasExplicitTemplateArgs(HasExplicitTemplateArgs)
- {}
+ const TemplateArgumentListInfo *Args);
public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
@@ -1669,6 +1913,7 @@ public:
const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to.
@@ -1740,7 +1985,7 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range(QualifierRange.getBegin(), getLocation());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
@@ -1752,25 +1997,32 @@ public:
}
static bool classof(const DependentScopeDeclRefExpr *) { return true; }
- virtual StmtIterator child_begin();
- virtual StmtIterator child_end();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
-class CXXExprWithTemporaries : public Expr {
+/// Represents an expression --- generally a full-expression --- which
+/// introduces cleanups to be run at the end of the sub-expression's
+/// evaluation. The most common source of expression-introduced
+/// cleanups is temporary objects in C++, but several other C++
+/// expressions can create cleanups.
+class ExprWithCleanups : public Expr {
Stmt *SubExpr;
CXXTemporary **Temps;
unsigned NumTemps;
- CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps,
- unsigned NumTemps);
-
+ ExprWithCleanups(ASTContext &C, Expr *SubExpr,
+ CXXTemporary **Temps, unsigned NumTemps);
+
public:
- CXXExprWithTemporaries(EmptyShell Empty)
- : Expr(CXXExprWithTemporariesClass, Empty),
+ ExprWithCleanups(EmptyShell Empty)
+ : Expr(ExprWithCleanupsClass, Empty),
SubExpr(0), Temps(0), NumTemps(0) {}
- static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
+ static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps);
@@ -1782,7 +2034,7 @@ public:
return Temps[i];
}
const CXXTemporary *getTemporary(unsigned i) const {
- return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i);
+ return const_cast<ExprWithCleanups*>(this)->getTemporary(i);
}
void setTemporary(unsigned i, CXXTemporary *T) {
assert(i < NumTemps && "Index out of range");
@@ -1793,19 +2045,18 @@ public:
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXExprWithTemporariesClass;
+ return T->getStmtClass() == ExprWithCleanupsClass;
}
- static bool classof(const CXXExprWithTemporaries *) { return true; }
+ static bool classof(const ExprWithCleanups *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
/// \brief Describes an explicit type conversion that uses functional
@@ -1830,12 +2081,9 @@ public:
/// constructor call, conversion function call, or some kind of type
/// conversion.
class CXXUnresolvedConstructExpr : public Expr {
- /// \brief The starting location of the type
- SourceLocation TyBeginLoc;
-
/// \brief The type being constructed.
- QualType Type;
-
+ TypeSourceInfo *Type;
+
/// \brief The location of the left parentheses ('(').
SourceLocation LParenLoc;
@@ -1845,20 +2093,20 @@ class CXXUnresolvedConstructExpr : public Expr {
/// \brief The number of arguments used to construct the type.
unsigned NumArgs;
- CXXUnresolvedConstructExpr(SourceLocation TyBegin,
- QualType T,
+ CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
Expr **Args,
unsigned NumArgs,
SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
- : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) { }
+ : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
+ friend class ASTStmtReader;
+
public:
static CXXUnresolvedConstructExpr *Create(ASTContext &C,
- SourceLocation TyBegin,
- QualType T,
+ TypeSourceInfo *Type,
SourceLocation LParenLoc,
Expr **Args,
unsigned NumArgs,
@@ -1867,15 +2115,14 @@ public:
static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C,
unsigned NumArgs);
- /// \brief Retrieve the source location where the type begins.
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
-
/// \brief Retrieve the type that is being constructed, as specified
/// in the source code.
- QualType getTypeAsWritten() const { return Type; }
- void setTypeAsWritten(QualType T) { Type = T; }
+ QualType getTypeAsWritten() const { return Type->getType(); }
+ /// \brief Retrieve the type source information for the type being
+ /// constructed.
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+
/// \brief Retrieve the location of the left parentheses ('(') that
/// precedes the argument list.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -1916,17 +2163,18 @@ public:
*(arg_begin() + I) = E;
}
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedConstructExprClass;
}
static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this+1);
+ return child_range(begin, begin + NumArgs);
+ }
};
/// \brief Represents a C++ member access expression where the actual
@@ -1987,19 +2235,13 @@ class CXXDependentScopeMemberExpr : public Expr {
public:
CXXDependentScopeMemberExpr(ASTContext &C,
- Expr *Base, QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo)
- : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
- Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
- Qualifier(Qualifier), QualifierRange(QualifierRange),
- FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- MemberNameInfo(MemberNameInfo) { }
+ Expr *Base, QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo);
static CXXDependentScopeMemberExpr *
Create(ASTContext &C,
@@ -2012,7 +2254,8 @@ public:
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
- CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@@ -2147,7 +2390,7 @@ public:
return getExplicitTemplateArgs().RAngleLoc;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range;
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
@@ -2169,8 +2412,13 @@ public:
static bool classof(const CXXDependentScopeMemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// \brief Represents a C++ member access expression for which lookup
@@ -2206,8 +2454,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent,
- bool HasUnresolvedUsing,
+ UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@@ -2222,7 +2469,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
public:
static UnresolvedMemberExpr *
- Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
+ Create(ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@@ -2232,7 +2479,8 @@ public:
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
static UnresolvedMemberExpr *
- CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@@ -2337,7 +2585,7 @@ public:
return getExplicitTemplateArgs().RAngleLoc;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range = getMemberNameInfo().getSourceRange();
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
@@ -2355,10 +2603,130 @@ public:
static bool classof(const UnresolvedMemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+};
+
+/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]).
+///
+/// The noexcept expression tests whether a given expression might throw. Its
+/// result is a boolean constant.
+class CXXNoexceptExpr : public Expr {
+ bool Value : 1;
+ Stmt *Operand;
+ SourceRange Range;
+
+ friend class ASTStmtReader;
+
+public:
+ CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
+ SourceLocation Keyword, SourceLocation RParen)
+ : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
+ /*TypeDependent*/false,
+ /*ValueDependent*/Val == CT_Dependent,
+ Operand->containsUnexpandedParameterPack()),
+ Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen)
+ { }
+
+ CXXNoexceptExpr(EmptyShell Empty)
+ : Expr(CXXNoexceptExprClass, Empty)
+ { }
+
+ Expr *getOperand() const { return static_cast<Expr*>(Operand); }
+
+ SourceRange getSourceRange() const { return Range; }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNoexceptExprClass;
+ }
+ static bool classof(const CXXNoexceptExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Operand, &Operand + 1); }
};
+/// \brief Represents a C++0x pack expansion that produces a sequence of
+/// expressions.
+///
+/// A pack expansion expression contains a pattern (which itself is an
+/// expression) followed by an ellipsis. For example:
+///
+/// \code
+/// template<typename F, typename ...Types>
+/// void forward(F f, Types &&...args) {
+/// f(static_cast<Types&&>(args)...);
+/// }
+/// \endcode
+///
+/// Here, the argument to the function object \c f is a pack expansion whose
+/// pattern is \c static_cast<Types&&>(args). When the \c forward function
+/// template is instantiated, the pack expansion will instantiate to zero or
+/// or more function arguments to the function object \c f.
+class PackExpansionExpr : public Expr {
+ SourceLocation EllipsisLoc;
+
+ /// \brief The number of expansions that will be produced by this pack
+ /// expansion expression, if known.
+ ///
+ /// When zero, the number of expansions is not known. Otherwise, this value
+ /// is the number of expansions + 1.
+ unsigned NumExpansions;
+
+ Stmt *Pattern;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions)
+ : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
+ Pattern->getObjectKind(), /*TypeDependent=*/true,
+ /*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false),
+ EllipsisLoc(EllipsisLoc),
+ NumExpansions(NumExpansions? *NumExpansions + 1 : 0),
+ Pattern(Pattern) { }
+
+ PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the location of the ellipsis that describes this pack
+ /// expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// \brief Determine the number of expansions that will be produced when
+ /// this pack expansion is instantiated, if already known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Pattern->getLocStart(), EllipsisLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PackExpansionExprClass;
+ }
+ static bool classof(const PackExpansionExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Pattern, &Pattern + 1);
+ }
+};
+
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
if (isa<UnresolvedLookupExpr>(this))
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
@@ -2366,6 +2734,159 @@ inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs();
}
+/// \brief Represents an expression that computes the length of a parameter
+/// pack.
+///
+/// \code
+/// template<typename ...Types>
+/// struct count {
+/// static const unsigned value = sizeof...(Types);
+/// };
+/// \endcode
+class SizeOfPackExpr : public Expr {
+ /// \brief The location of the 'sizeof' keyword.
+ SourceLocation OperatorLoc;
+
+ /// \brief The location of the name of the parameter pack.
+ SourceLocation PackLoc;
+
+ /// \brief The location of the closing parenthesis.
+ SourceLocation RParenLoc;
+
+ /// \brief The length of the parameter pack, if known.
+ ///
+ /// When this expression is value-dependent, the length of the parameter pack
+ /// is unknown. When this expression is not value-dependent, the length is
+ /// known.
+ unsigned Length;
+
+ /// \brief The parameter pack itself.
+ NamedDecl *Pack;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ /// \brief Creates a value-dependent expression that computes the length of
+ /// the given parameter pack.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/true,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(0), Pack(Pack) { }
+
+ /// \brief Creates an expression that computes the length of
+ /// the given parameter pack, which is already known.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc,
+ unsigned Length)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(Length), Pack(Pack) { }
+
+ /// \brief Create an empty expression.
+ SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { }
+
+ /// \brief Determine the location of the 'sizeof' keyword.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Determine the location of the parameter pack.
+ SourceLocation getPackLoc() const { return PackLoc; }
+
+ /// \brief Determine the location of the right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// \brief Retrieve the parameter pack.
+ NamedDecl *getPack() const { return Pack; }
+
+ /// \brief Retrieve the length of the parameter pack.
+ ///
+ /// This routine may only be invoked when the expression is not
+ /// value-dependent.
+ unsigned getPackLength() const {
+ assert(!isValueDependent() &&
+ "Cannot get the length of a value-dependent pack size expression");
+ return Length;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(OperatorLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfPackExprClass;
+ }
+ static bool classof(const SizeOfPackExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// \brief Represents a reference to a non-type template parameter pack that
+/// has been substituted with a non-template argument pack.
+///
+/// When a pack expansion in the source code contains multiple parameter packs
+/// and those parameter packs correspond to different levels of template
+/// parameter lists, this node node is used to represent a non-type template
+/// parameter pack from an outer level, which has already had its argument pack
+/// substituted but that still lives within a pack expansion that itself
+/// could not be instantiated. When actually performing a substitution into
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the appropriate underlying
+/// expression at the current pack substitution index.
+class SubstNonTypeTemplateParmPackExpr : public Expr {
+ /// \brief The non-type template parameter pack itself.
+ NonTypeTemplateParmDecl *Param;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ /// \brief The location of the non-type template parameter pack reference.
+ SourceLocation NameLoc;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack);
+
+ SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+
+ /// \brief Retrieve the non-type template parameter pack being substituted.
+ NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
+
+ /// \brief Retrieve the location of the parameter pack name.
+ SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+ /// \brief Retrieve the template argument pack containing the substituted
+ /// template arguments.
+ TemplateArgument getArgumentPack() const;
+
+ SourceRange getSourceRange() const { return NameLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
+ }
+ static bool classof(const SubstNonTypeTemplateParmPackExpr *) {
+ return true;
+ }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 8a09f4e9a6a9..285efb757bbb 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -14,14 +14,13 @@
#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
class IdentifierInfo;
class ASTContext;
- class ObjCMethodDecl;
- class ObjCPropertyDecl;
/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
@@ -30,7 +29,9 @@ class ObjCStringLiteral : public Expr {
SourceLocation AtLoc;
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
- : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {}
+ : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ String(SL), AtLoc(L) {}
explicit ObjCStringLiteral(EmptyShell Empty)
: Expr(ObjCStringLiteralClass, Empty) {}
@@ -41,7 +42,7 @@ public:
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, String->getLocEnd());
}
@@ -51,8 +52,7 @@ public:
static bool classof(const ObjCStringLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&String, &String+1); }
};
/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
@@ -64,8 +64,10 @@ class ObjCEncodeExpr : public Expr {
public:
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(),
- EncodedType->getType()->isDependentType()),
+ : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->containsUnexpandedParameterPack()),
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
@@ -83,7 +85,7 @@ public:
EncodedType = EncType;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -93,8 +95,7 @@ public:
static bool classof(const ObjCEncodeExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCSelectorExpr used for @selector in Objective-C.
@@ -104,8 +105,9 @@ class ObjCSelectorExpr : public Expr {
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at),
- RParenLoc(rp){}
+ : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ SelName(selInfo), AtLoc(at), RParenLoc(rp){}
explicit ObjCSelectorExpr(EmptyShell Empty)
: Expr(ObjCSelectorExprClass, Empty) {}
@@ -117,7 +119,7 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -130,8 +132,7 @@ public:
static bool classof(const ObjCSelectorExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used
@@ -144,8 +145,9 @@ class ObjCProtocolExpr : public Expr {
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol),
- AtLoc(at), RParenLoc(rp) {}
+ : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
@@ -157,7 +159,7 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -167,8 +169,7 @@ public:
static bool classof(const ObjCProtocolExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
@@ -180,13 +181,13 @@ class ObjCIvarRefExpr : public Expr {
bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
public:
- ObjCIvarRefExpr(ObjCIvarDecl *d,
- QualType t, SourceLocation l, Expr *base,
+ ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
+ SourceLocation l, Expr *base,
bool arrow = false, bool freeIvar = false) :
- Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()), D(d),
- Loc(l), Base(base), IsArrow(arrow),
- IsFreeIvar(freeIvar) {}
+ Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {}
explicit ObjCIvarRefExpr(EmptyShell Empty)
: Expr(ObjCIvarRefExprClass, Empty) {}
@@ -207,7 +208,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return isFreeIvar() ? SourceRange(Loc)
: SourceRange(getBase()->getLocStart(), Loc);
}
@@ -218,8 +219,7 @@ public:
static bool classof(const ObjCIvarRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
@@ -227,32 +227,127 @@ public:
///
class ObjCPropertyRefExpr : public Expr {
private:
- ObjCPropertyDecl *AsProperty;
+ /// If the bool is true, this is an implicit property reference; the
+ /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
+ /// if the bool is false, this is an explicit property reference;
+ /// the pointer is an ObjCPropertyDecl and Setter is always null.
+ llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
+ ObjCMethodDecl *Setter;
+
SourceLocation IdLoc;
- Stmt *Base;
+
+ /// \brief When the receiver in property access is 'super', this is
+ /// the location of the 'super' keyword. When it's an interface,
+ /// this is that interface.
+ SourceLocation ReceiverLoc;
+ llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
+
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, Expr *base)
- : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()),
- AsProperty(PD), IdLoc(l), Base(base) {
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(), Receiver(base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, SourceLocation sl, QualType st)
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, false,
+ st->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc, Expr *Base)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
+ Base->isValueDependent(),
+ Base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation SuperLoc, QualType SuperTy)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
}
explicit ObjCPropertyRefExpr(EmptyShell Empty)
: Expr(ObjCPropertyRefExprClass, Empty) {}
- ObjCPropertyDecl *getProperty() const { return AsProperty; }
- void setProperty(ObjCPropertyDecl *D) { AsProperty = D; }
+ bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
+ bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
- const Expr *getBase() const { return cast<Expr>(Base); }
- Expr *getBase() { return cast<Expr>(Base); }
- void setBase(Expr *base) { Base = base; }
+ ObjCPropertyDecl *getExplicitProperty() const {
+ assert(!isImplicitProperty());
+ return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertyGetter() const {
+ assert(isImplicitProperty());
+ return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertySetter() const {
+ assert(isImplicitProperty());
+ return Setter;
+ }
+
+ Selector getGetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertyGetter()->getSelector();
+ return getExplicitProperty()->getGetterName();
+ }
+
+ Selector getSetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertySetter()->getSelector();
+ return getExplicitProperty()->getSetterName();
+ }
+
+ const Expr *getBase() const {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
+ Expr *getBase() {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
SourceLocation getLocation() const { return IdLoc; }
- void setLocation(SourceLocation L) { IdLoc = L; }
+
+ SourceLocation getReceiverLocation() const { return ReceiverLoc; }
+ QualType getSuperReceiverType() const {
+ return QualType(Receiver.get<const Type*>(), 0);
+ }
+ ObjCInterfaceDecl *getClassReceiver() const {
+ return Receiver.get<ObjCInterfaceDecl*>();
+ }
+ bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
+ bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
+ bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
- virtual SourceRange getSourceRange() const {
- return SourceRange(getBase()->getLocStart(), IdLoc);
+ SourceRange getSourceRange() const {
+ return SourceRange((isObjectReceiver() ? getBase()->getLocStart()
+ : getReceiverLocation()),
+ IdLoc);
}
static bool classof(const Stmt *T) {
@@ -261,89 +356,32 @@ public:
static bool classof(const ObjCPropertyRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
-
-/// 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;
- /// 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 *InterfaceDecl;
- /// Location of the receiver class in the dot syntax notation
- /// used to call a class method setter/getter.
- SourceLocation ClassLoc;
-
-public:
- ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
- QualType t,
- ObjCMethodDecl *setter,
- SourceLocation l, Expr *base)
- : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()),
- Setter(setter), Getter(getter), MemberLoc(l), Base(base),
- InterfaceDecl(0), ClassLoc(SourceLocation()) {
- }
- ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
- QualType t,
- ObjCMethodDecl *setter,
- SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
- : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
- Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C),
- ClassLoc(CL) {
+ child_range children() {
+ if (Receiver.is<Stmt*>()) {
+ Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
+ return child_range(begin, begin+1);
}
- explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty)
- : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){}
-
- ObjCMethodDecl *getGetterMethod() const { return Getter; }
- ObjCMethodDecl *getSetterMethod() const { return Setter; }
- ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; }
- void setGetterMethod(ObjCMethodDecl *D) { Getter = D; }
- void setSetterMethod(ObjCMethodDecl *D) { Setter = D; }
- void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; }
-
- virtual SourceRange getSourceRange() const {
- if (Base)
- 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 MemberLoc; }
- void setLocation(SourceLocation L) { MemberLoc = L; }
- SourceLocation getClassLoc() const { return ClassLoc; }
- void setClassLoc(SourceLocation L) { ClassLoc = L; }
+ return child_range();
+ }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass;
+private:
+ friend class ASTStmtReader;
+ void setExplicitProperty(ObjCPropertyDecl *D) {
+ PropertyOrGetter.setPointer(D);
+ PropertyOrGetter.setInt(false);
+ Setter = 0;
+ }
+ void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) {
+ PropertyOrGetter.setPointer(Getter);
+ PropertyOrGetter.setInt(true);
+ this->Setter = Setter;
}
- static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; }
+ void setBase(Expr *Base) { Receiver = Base; }
+ void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
+ void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ void setLocation(SourceLocation L) { IdLoc = L; }
+ void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
};
/// \brief An expression that sends a message to the given Objective-C
@@ -396,6 +434,9 @@ class ObjCMessageExpr : public Expr {
/// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod;
+ /// \brief Location of the selector.
+ SourceLocation SelectorLoc;
+
/// \brief The source locations of the open and close square
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
@@ -404,26 +445,29 @@ class ObjCMessageExpr : public Expr {
: Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0),
HasMethod(0), SelectorOrMethod(0) { }
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -458,6 +502,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param SuperLoc The location of the "super" keyword.
@@ -475,12 +523,14 @@ public:
/// \param NumArgs The number of arguments.
///
/// \param RBracLoc The location of the closing square bracket ']'.
- static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -491,6 +541,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param Receiver The type of the receiver, including
@@ -507,9 +561,11 @@ public:
///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -520,6 +576,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param Receiver The expression used to produce the object that
@@ -536,9 +596,11 @@ public:
///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -556,6 +618,9 @@ public:
/// sent to.
ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
+ /// \brief Source range of the receiver.
+ SourceRange getReceiverRange() const;
+
/// \brief Determine whether this is an instance message to either a
/// computed object or to super.
bool isInstanceMessage() const {
@@ -682,11 +747,11 @@ public:
/// \brief Retrieve the arguments to this message, not including the
/// receiver.
- Stmt **getArgs() {
- return reinterpret_cast<Stmt **>(this + 1) + 1;
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(this + 1) + 1;
}
- const Stmt * const *getArgs() const {
- return reinterpret_cast<const Stmt * const *>(this + 1) + 1;
+ const Expr * const *getArgs() const {
+ return reinterpret_cast<const Expr * const *>(this + 1) + 1;
}
/// getArg - Return the specified argument.
@@ -706,15 +771,13 @@ public:
SourceLocation getLeftLoc() const { return LBracLoc; }
SourceLocation getRightLoc() const { return RBracLoc; }
-
- void setLeftLoc(SourceLocation L) { LBracLoc = L; }
- void setRightLoc(SourceLocation L) { RBracLoc = L; }
+ SourceLocation getSelectorLoc() const { return SelectorLoc; }
void setSourceRange(SourceRange R) {
LBracLoc = R.getBegin();
RBracLoc = R.getEnd();
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
}
@@ -724,43 +787,24 @@ public:
static bool classof(const ObjCMessageExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children();
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
- arg_iterator arg_begin() { return getArgs(); }
- arg_iterator arg_end() { return getArgs() + NumArgs; }
- const_arg_iterator arg_begin() const { return getArgs(); }
- const_arg_iterator arg_end() const { return getArgs() + NumArgs; }
-};
-
-/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
-/// which refers to the object on which the current method is executing.
-///
-/// FIXME: This class is intended for removal, once its remaining
-/// clients have been altered to represent "super" internally.
-class ObjCSuperExpr : public Expr {
- SourceLocation Loc;
-public:
- ObjCSuperExpr(SourceLocation L, QualType Type)
- : Expr(ObjCSuperExprClass, Type, false, false), 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) {
- return T->getStmtClass() == ObjCSuperExprClass;
+ arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
+ arg_iterator arg_end() {
+ return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
+ }
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs());
+ }
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
}
- static bool classof(const ObjCSuperExpr *) { return true; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
@@ -776,8 +820,9 @@ class ObjCIsaExpr : public Expr {
bool IsArrow;
public:
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
- : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false,
- base->isValueDependent()),
+ : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ /*ContainsUnexpandedParameterPack=*/false),
Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
/// \brief Build an empty expression.
@@ -794,11 +839,11 @@ public:
SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
}
- virtual SourceLocation getExprLoc() const { return IsaMemberLoc; }
+ SourceLocation getExprLoc() const { return IsaMemberLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIsaExprClass;
@@ -806,8 +851,7 @@ public:
static bool classof(const ObjCIsaExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
} // end namespace clang
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index a8ef0053a442..7b23766b0714 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#include "clang/AST/DeclBase.h"
#include <cassert>
#include <vector>
@@ -24,6 +25,7 @@ template <class T> class SmallVectorImpl;
namespace clang {
class ASTConsumer;
+class CXXBaseSpecifier;
class Decl;
class DeclContext;
class DeclContextLookupResult;
@@ -32,6 +34,7 @@ class ExternalSemaSource; // layering violation required for downcasting
class NamedDecl;
class Selector;
class Stmt;
+class TagDecl;
/// \brief Abstract interface for external sources of AST nodes.
///
@@ -91,6 +94,10 @@ public:
/// FunctionDecl::setLazyBody when building decls.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0;
+
/// \brief Finds all declarations with the given name in the
/// given context.
///
@@ -110,12 +117,44 @@ public:
virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
/// \brief Finds all declarations lexically contained within the given
- /// DeclContext.
+ /// DeclContext, after applying an optional filter predicate.
+ ///
+ /// \param isKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for. If NULL, all declarations
+ /// are returned.
///
/// \return true if an error occurred
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
- llvm::SmallVectorImpl<Decl*> &Result) = 0;
+ bool (*isKindWeWant)(Decl::Kind),
+ llvm::SmallVectorImpl<Decl*> &Result) = 0;
+
+ /// \brief Finds all declarations lexically contained within the given
+ /// DeclContext.
+ ///
+ /// \return true if an error occurred
+ bool FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, 0, Result);
+ }
+
+ template <typename DeclTy>
+ bool FindExternalLexicalDeclsBy(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
+ }
+
+ /// \brief Gives the external AST source an opportunity to complete
+ /// an incomplete type.
+ virtual void CompleteType(TagDecl *Tag) {}
+ /// \brief Gives the external AST source an opportunity to complete an
+ /// incomplete Objective-C class.
+ ///
+ /// This routine will only be invoked if the "externally completed" bit is
+ /// set on the ObjCInterfaceDecl via the function
+ /// \c ObjCInterfaceDecl::setExternallyCompleted().
+ virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+
/// \brief Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
@@ -227,6 +266,11 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
+/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>
+ LazyCXXBaseSpecifiersPtr;
+
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h
deleted file mode 100644
index 6ceefed8a63a..000000000000
--- a/include/clang/AST/FullExpr.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//===--- FullExpr.h - C++ full expression class -----------------*- 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 FullExpr interface, to be used for type safe handling
-// of full expressions.
-//
-// Full expressions are described in C++ [intro.execution]p12.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_FULLEXPR_H
-#define LLVM_CLANG_AST_FULLEXPR_H
-
-#include "llvm/ADT/PointerUnion.h"
-
-namespace clang {
- class ASTContext;
- class CXXTemporary;
- class Expr;
-
-class FullExpr {
- struct ExprAndTemporaries {
- Expr *SubExpr;
-
- unsigned NumTemps;
-
- typedef CXXTemporary** temps_iterator;
-
- temps_iterator temps_begin() {
- return reinterpret_cast<CXXTemporary **>(this + 1);
- }
- temps_iterator temps_end() {
- return temps_begin() + NumTemps;
- }
- };
-
- typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy;
- SubExprTy SubExpr;
-
- FullExpr() { }
-
-public:
- static FullExpr Create(ASTContext &Context, Expr *SubExpr,
- CXXTemporary **Temps, unsigned NumTemps);
-
- Expr *getExpr() {
- if (Expr *E = SubExpr.dyn_cast<Expr *>())
- return E;
-
- return SubExpr.get<ExprAndTemporaries *>()->SubExpr;
- }
-
- const Expr *getExpr() const {
- return const_cast<FullExpr*>(this)->getExpr();
- }
-
- typedef CXXTemporary** temps_iterator;
-
- temps_iterator temps_begin() {
- if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
- return ET->temps_begin();
-
- return 0;
- }
- temps_iterator temps_end() {
- if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
- return ET->temps_end();
-
- return 0;
- }
-
- void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); }
-
- static FullExpr getFromOpaquePtr(void *Ptr) {
- FullExpr E;
- E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr);
- return E;
- }
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
new file mode 100644
index 000000000000..7af7702027a4
--- /dev/null
+++ b/include/clang/AST/Mangle.h
@@ -0,0 +1,150 @@
+//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the C++ name mangling interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MANGLE_H
+#define LLVM_CLANG_AST_MANGLE_H
+
+#include "clang/AST/Type.h"
+#include "clang/Basic/ABI.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+ class ASTContext;
+ class BlockDecl;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class FunctionDecl;
+ class NamedDecl;
+ class ObjCMethodDecl;
+ class VarDecl;
+ struct ThisAdjustment;
+ struct ThunkInfo;
+
+/// MangleBuffer - a convenient class for storing a name which is
+/// either the result of a mangling or is a constant string with
+/// external memory ownership.
+class MangleBuffer {
+public:
+ void setString(llvm::StringRef Ref) {
+ String = Ref;
+ }
+
+ llvm::SmallVectorImpl<char> &getBuffer() {
+ return Buffer;
+ }
+
+ llvm::StringRef getString() const {
+ if (!String.empty()) return String;
+ return Buffer.str();
+ }
+
+ operator llvm::StringRef() const {
+ return getString();
+ }
+
+private:
+ llvm::StringRef String;
+ llvm::SmallString<256> Buffer;
+};
+
+/// MangleContext - Context for tracking state which persists across multiple
+/// calls to the C++ name mangler.
+class MangleContext {
+ ASTContext &Context;
+ Diagnostic &Diags;
+
+ llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
+ llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
+
+public:
+ explicit MangleContext(ASTContext &Context,
+ Diagnostic &Diags)
+ : Context(Context), Diags(Diags) { }
+
+ virtual ~MangleContext() { }
+
+ ASTContext &getASTContext() const { return Context; }
+
+ Diagnostic &getDiags() const { return Diags; }
+
+ virtual void startNewFunction() { LocalBlockIds.clear(); }
+
+ unsigned getBlockId(const BlockDecl *BD, bool Local) {
+ llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
+ = Local? LocalBlockIds : GlobalBlockIds;
+ std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
+ Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
+ return Result.first->second;
+ }
+
+ /// @name Mangler Entry Points
+ /// @{
+
+ virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
+ virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &)=0;
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleReferenceTemporary(const VarDecl *D,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ llvm::raw_ostream &) = 0;
+
+ void mangleGlobalBlock(const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ // Do the right thing.
+ void mangleBlock(const BlockDecl *BD, llvm::raw_ostream &Out);
+
+ void mangleObjCMethodName(const ObjCMethodDecl *MD,
+ llvm::raw_ostream &);
+
+ // This is pretty lame.
+ virtual void mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::raw_ostream &) {
+ assert(0 && "Target does not support mangling guard variables");
+ }
+ /// @}
+};
+
+MangleContext *createItaniumMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+MangleContext *createMicrosoftMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+
+}
+
+#endif
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 3b25f3bb403f..99cc1f268fb2 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -90,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(const ASTContext &Context,
const NestedNameSpecifier &Mockup);
public:
@@ -99,19 +99,19 @@ 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,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
/// \brief Builds a nested name specifier that names a namespace.
- static NestedNameSpecifier *Create(ASTContext &Context,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
/// \brief Builds a nested name specifier that names a type.
- static NestedNameSpecifier *Create(ASTContext &Context,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
- bool Template, Type *T);
+ bool Template, const Type *T);
/// \brief Builds a specifier that consists of just an identifier.
///
@@ -119,11 +119,12 @@ public:
/// 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);
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ IdentifierInfo *II);
/// \brief Returns the nested name specifier representing the global
/// scope.
- static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
+ static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
/// \brief Return the prefix of this nested name specifier.
///
@@ -160,10 +161,10 @@ public:
}
/// \brief Retrieve the type stored in this nested name specifier.
- Type *getAsType() const {
+ const Type *getAsType() const {
if (Prefix.getInt() == TypeSpec ||
Prefix.getInt() == TypeSpecWithTemplate)
- return (Type *)Specifier;
+ return (const Type *)Specifier;
return 0;
}
@@ -172,6 +173,10 @@ public:
/// type or not.
bool isDependent() const;
+ /// \brief Whether this nested-name-specifier contains an unexpanded
+ /// parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
/// \brief Print this nested name specifier to the given output
/// stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index 804531192971..35c72c45ce7c 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -17,107 +17,238 @@
namespace clang {
-/// CastKind - the kind of cast this represents.
+/// CastKind - The kind of operation required for a conversion.
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_Dependent - A conversion which cannot yet be analyzed because
+ /// either the expression or target type is dependent. These are
+ /// created only for explicit casts; dependent ASTs aren't required
+ /// to even approximately type-check.
+ /// (T*) malloc(sizeof(T))
+ /// reinterpret_cast<intptr_t>(A<T>::alloc());
+ CK_Dependent,
- /// CK_BitCast - Used for reinterpret_cast.
+ /// CK_BitCast - A conversion which causes a bit pattern of one type
+ /// to be reinterpreted as a bit pattern of another type. Generally
+ /// the operands must have equivalent size and unrelated types.
+ ///
+ /// The pointer conversion char* -> int* is a bitcast. Many other
+ /// pointer conversions which are "physically" bitcasts are given
+ /// special cast kinds.
+ ///
+ /// Vector coercions are bitcasts.
CK_BitCast,
- /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
- /// a reference type.
+ /// CK_LValueBitCast - A conversion which reinterprets the address of
+ /// an l-value as an l-value of a different kind. Used for
+ /// reinterpret_casts of l-value expressions to reference types.
+ /// bool b; reinterpret_cast<char&>(b) = 'a';
CK_LValueBitCast,
+
+ /// CK_LValueToRValue - A conversion which causes the extraction of
+ /// an r-value from the operand gl-value. The result of an r-value
+ /// conversion is always unqualified.
+ CK_LValueToRValue,
+
+ /// CK_GetObjCProperty - A conversion which calls an Objective-C
+ /// property getter. The operand is an OK_ObjCProperty l-value; the
+ /// result will generally be an r-value, but could be an ordinary
+ /// gl-value if the property reference is to an implicit property
+ /// for a method that returns a reference type.
+ CK_GetObjCProperty,
- /// CK_NoOp - Used for const_cast.
+ /// CK_NoOp - A conversion which does not affect the type other than
+ /// (possibly) adding qualifiers.
+ /// int -> int
+ /// char** -> const char * const *
CK_NoOp,
- /// CK_BaseToDerived - Base to derived class casts.
+ /// CK_BaseToDerived - A conversion from a C++ class pointer/reference
+ /// to a derived class pointer/reference.
+ /// B *b = static_cast<B*>(a);
CK_BaseToDerived,
- /// CK_DerivedToBase - Derived to base class casts.
+ /// CK_DerivedToBase - A conversion from a C++ class pointer
+ /// to a base class pointer.
+ /// A *a = new B();
CK_DerivedToBase,
- /// CK_UncheckedDerivedToBase - Derived to base class casts that
- /// assume that the derived pointer is not null.
+ /// CK_UncheckedDerivedToBase - A conversion from a C++ class
+ /// pointer/reference to a base class that can assume that the
+ /// derived pointer is not null.
+ /// const A &a = B();
+ /// b->method_from_a();
CK_UncheckedDerivedToBase,
- /// CK_Dynamic - Dynamic cast.
+ /// CK_Dynamic - A C++ dynamic_cast.
CK_Dynamic,
- /// CK_ToUnion - Cast to union (GCC extension).
+ /// CK_ToUnion - The GCC cast-to-union extension.
+ /// int -> union { int x; float y; }
+ /// float -> union { int x; float y; }
CK_ToUnion,
/// CK_ArrayToPointerDecay - Array to pointer decay.
+ /// int[10] -> int*
+ /// char[5][6] -> char(*)[6]
CK_ArrayToPointerDecay,
- // CK_FunctionToPointerDecay - Function to pointer decay.
+ /// CK_FunctionToPointerDecay - Function to pointer decay.
+ /// void(int) -> void(*)(int)
CK_FunctionToPointerDecay,
- /// CK_NullToMemberPointer - Null pointer to member pointer.
+ /// CK_NullToPointer - Null pointer constant to pointer, ObjC
+ /// pointer, or block pointer.
+ /// (void*) 0
+ /// void (^block)() = 0;
+ CK_NullToPointer,
+
+ /// CK_NullToMemberPointer - Null pointer constant to member pointer.
+ /// int A::*mptr = 0;
+ /// int (A::*fptr)(int) = nullptr;
CK_NullToMemberPointer,
/// CK_BaseToDerivedMemberPointer - Member pointer in base class to
/// member pointer in derived class.
+ /// int B::*mptr = &A::member;
CK_BaseToDerivedMemberPointer,
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
/// member pointer in base class.
+ /// int A::*mptr = static_cast<int A::*>(&B::member);
CK_DerivedToBaseMemberPointer,
+ /// CK_MemberPointerToBoolean - Member pointer to boolean. A check
+ /// against the null member pointer.
+ CK_MemberPointerToBoolean,
+
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
+ /// struct A { operator int(); }; int i = int(A());
CK_UserDefinedConversion,
- /// CK_ConstructorConversion - Conversion by constructor
+ /// CK_ConstructorConversion - Conversion by constructor.
+ /// struct A { A(int); }; A a = A(10);
CK_ConstructorConversion,
- /// CK_IntegralToPointer - Integral to pointer
+ /// CK_IntegralToPointer - Integral to pointer. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (char*) 0x1001aab0
+ /// reinterpret_cast<int*>(0)
CK_IntegralToPointer,
- /// CK_PointerToIntegral - Pointer to integral
+ /// CK_PointerToIntegral - Pointer to integral. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (intptr_t) "help!"
CK_PointerToIntegral,
+
+ /// CK_PointerToBoolean - Pointer to boolean conversion. A check
+ /// against null. Applies to normal, ObjC, and block pointers.
+ CK_PointerToBoolean,
- /// CK_ToVoid - Cast to void.
+ /// CK_ToVoid - Cast to void, discarding the computed value.
+ /// (void) malloc(2048)
CK_ToVoid,
- /// CK_VectorSplat - Casting from an integer/floating type to an extended
- /// vector type with the same element type as the src type. Splats the
- /// src expression into the destination expression.
+ /// CK_VectorSplat - A conversion from an arithmetic type to a
+ /// vector of that element type. Fills all elements ("splats") with
+ /// the source value.
+ /// __attribute__((ext_vector_type(4))) int v = 5;
CK_VectorSplat,
- /// CK_IntegralCast - Casting between integral types of different size.
+ /// CK_IntegralCast - A cast between integral types (other than to
+ /// boolean). Variously a bitcast, a truncation, a sign-extension,
+ /// or a zero-extension.
+ /// long l = 5;
+ /// (unsigned) i
CK_IntegralCast,
+ /// CK_IntegralToBoolean - Integral to boolean. A check against zero.
+ /// (bool) i
+ CK_IntegralToBoolean,
+
/// CK_IntegralToFloating - Integral to floating point.
+ /// float f = i;
CK_IntegralToFloating,
- /// CK_FloatingToIntegral - Floating point to integral.
+ /// CK_FloatingToIntegral - Floating point to integral. Rounds
+ /// towards zero, discarding any fractional component.
+ /// (int) f
CK_FloatingToIntegral,
+
+ /// CK_FloatingToBoolean - Floating point to boolean.
+ /// (bool) f
+ CK_FloatingToBoolean,
/// CK_FloatingCast - Casting between floating types of different size.
+ /// (double) f
+ /// (float) ld
CK_FloatingCast,
- /// CK_MemberPointerToBoolean - Member pointer to boolean
- CK_MemberPointerToBoolean,
-
- /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
- /// pointer
+ /// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind
+ /// to an Objective-C pointer.
CK_AnyPointerToObjCPointerCast,
- /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
- /// pointer
+ /// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind
+ /// to a block pointer.
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
- CK_ObjCObjectLValueCast
+ CK_ObjCObjectLValueCast,
+
+ /// \brief A conversion of a floating point real to a floating point
+ /// complex of the original type. Injects the value as the real
+ /// component with a zero imaginary component.
+ /// float -> _Complex float
+ CK_FloatingRealToComplex,
+
+ /// \brief Converts a floating point complex to floating point real
+ /// of the source's element type. Just discards the imaginary
+ /// component.
+ /// _Complex long double -> long double
+ CK_FloatingComplexToReal,
+
+ /// \brief Converts a floating point complex to bool by comparing
+ /// against 0+0i.
+ CK_FloatingComplexToBoolean,
+
+ /// \brief Converts between different floating point complex types.
+ /// _Complex float -> _Complex double
+ CK_FloatingComplexCast,
+
+ /// \brief Converts from a floating complex to an integral complex.
+ /// _Complex float -> _Complex int
+ CK_FloatingComplexToIntegralComplex,
+
+ /// \brief Converts from an integral real to an integral complex
+ /// whose element type matches the source. Injects the value as
+ /// the real component with a zero imaginary component.
+ /// long -> _Complex long
+ CK_IntegralRealToComplex,
+
+ /// \brief Converts an integral complex to an integral real of the
+ /// source's element type by discarding the imaginary component.
+ /// _Complex short -> short
+ CK_IntegralComplexToReal,
+
+ /// \brief Converts an integral complex to bool by comparing against
+ /// 0+0i.
+ CK_IntegralComplexToBoolean,
+
+ /// \brief Converts between different integral complex types.
+ /// _Complex char -> _Complex long long
+ /// _Complex unsigned int -> _Complex signed int
+ CK_IntegralComplexCast,
+
+ /// \brief Converts from an integral complex to a floating complex.
+ /// _Complex unsigned -> _Complex float
+ CK_IntegralComplexToFloatingComplex
};
+#define CK_Invalid ((CastKind) -1)
enum BinaryOperatorKind {
// Operators listed in order of precedence.
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index f826e1117b66..9ea5a0930d32 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -24,8 +24,14 @@ public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
+ /// \brief Adds and/or updates the parent/child-relations of the complete
+ /// stmt tree of S. All children of S including indirect descendants are
+ /// visited and updated or inserted but not the parents of S.
+ void addStmt(Stmt* S);
+
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
+ Stmt *getParentIgnoreParenCasts(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
@@ -35,6 +41,10 @@ public:
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
+ const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
+ return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
+ }
+
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 70d65d35fef8..a59c302ffc1e 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+#include "clang/Basic/LangOptions.h"
+
namespace llvm {
class raw_ostream;
}
@@ -44,7 +46,7 @@ struct PrintingPolicy {
unsigned Indentation : 8;
/// \brief What language we're printing.
- const LangOptions &LangOpts;
+ const LangOptions LangOpts;
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 2b3229e8fae9..d7bab80afc5e 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -14,8 +14,9 @@
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
namespace clang {
@@ -32,93 +33,41 @@ namespace clang {
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
- /// Size - Size of record in bits.
- uint64_t Size;
+ /// Size - Size of record in characters.
+ CharUnits Size;
- /// DataSize - Size of record in bits without tail padding.
- uint64_t DataSize;
+ /// DataSize - Size of record in characters without tail padding.
+ CharUnits DataSize;
/// FieldOffsets - Array of field offsets in bits.
uint64_t *FieldOffsets;
- // Alignment - Alignment of record in bits.
- unsigned Alignment;
+ // Alignment - Alignment of record in characters.
+ CharUnits Alignment;
// FieldCount - Number of fields.
unsigned FieldCount;
-public:
- /// PrimaryBaseInfo - Contains info about a primary base.
- struct PrimaryBaseInfo {
- PrimaryBaseInfo() {}
-
- PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
- : Value(Base, Base && IsVirtual) {}
-
- /// Value - Points to the primary base. The single-bit value
- /// will be non-zero when the primary base is virtual.
- llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value;
-
- /// getBase - Returns the primary base.
- const CXXRecordDecl *getBase() const { return Value.getPointer(); }
-
- /// isVirtual - Returns whether the primary base is virtual or not.
- bool isVirtual() const { return Value.getInt(); }
-
- friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) {
- return X.Value == Y.Value;
- }
- };
-
- /// primary_base_info_iterator - An iterator for iterating the primary base
- /// class chain.
- class primary_base_info_iterator {
- /// Current - The current base class info.
- PrimaryBaseInfo Current;
-
- public:
- primary_base_info_iterator() {}
- primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {}
-
- const PrimaryBaseInfo &operator*() const { return Current; }
-
- primary_base_info_iterator& operator++() {
- const CXXRecordDecl *RD = Current.getBase();
- Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo();
- return *this;
- }
-
- friend bool operator==(const primary_base_info_iterator &X,
- const primary_base_info_iterator &Y) {
- return X.Current == Y.Current;
- }
- friend bool operator!=(const primary_base_info_iterator &X,
- const primary_base_info_iterator &Y) {
- return !(X == Y);
- }
- };
-
-private:
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
struct CXXRecordLayoutInfo {
- /// NonVirtualSize - The non-virtual size (in bits) of an object, which is
+ /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
/// the size of the object without virtual bases.
- uint64_t NonVirtualSize;
+ CharUnits NonVirtualSize;
- /// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
+ /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- uint64_t NonVirtualAlign;
+ CharUnits NonVirtualAlign;
/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
/// (either a base or a member). Will be zero if the class doesn't contain
/// any empty subobjects.
- uint64_t SizeOfLargestEmptySubobject;
+ CharUnits SizeOfLargestEmptySubobject;
/// PrimaryBase - The primary base info for this record.
- PrimaryBaseInfo PrimaryBase;
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
- typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy;
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
@@ -133,35 +82,35 @@ private:
friend class ASTContext;
- ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment,
- unsigned datasize, const uint64_t *fieldoffsets,
+ ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+ CharUnits datasize, const uint64_t *fieldoffsets,
unsigned fieldcount);
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
- ASTRecordLayout(ASTContext &Ctx,
- uint64_t size, unsigned alignment, uint64_t datasize,
+ ASTRecordLayout(const ASTContext &Ctx,
+ CharUnits size, CharUnits alignment, CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
- uint64_t nonvirtualsize, unsigned nonvirtualalign,
- uint64_t SizeOfLargestEmptySubobject,
+ CharUnits nonvirtualsize, CharUnits nonvirtualalign,
+ CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
- bool PrimaryBaseIsVirtual,
+ bool IsPrimaryBaseVirtual,
const BaseOffsetsMapTy& BaseOffsets,
const BaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}
void Destroy(ASTContext &Ctx);
-
+
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; }
+ /// getAlignment - Get the record alignment in characters.
+ CharUnits getAlignment() const { return Alignment; }
- /// getSize - Get the record size in bits.
- uint64_t getSize() const { return Size; }
+ /// getSize - Get the record size in characters.
+ CharUnits getSize() const { return Size; }
/// getFieldCount - Get the number of fields in the layout.
unsigned getFieldCount() const { return FieldCount; }
@@ -174,75 +123,81 @@ public:
}
/// getDataSize() - Get the record data size, which is the record size
- /// without tail padding, in bits.
- uint64_t getDataSize() const {
+ /// without tail padding, in characters.
+ CharUnits getDataSize() const {
return DataSize;
}
- /// getNonVirtualSize - Get the non-virtual size (in bits) of an object,
+ /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
/// which is the size of the object without virtual bases.
- uint64_t getNonVirtualSize() const {
+ CharUnits 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,
+ /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- unsigned getNonVirtualAlign() const {
+ CharUnits getNonVirtualAlign() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->NonVirtualAlign;
}
- /// getPrimaryBaseInfo - Get the primary base info.
- const PrimaryBaseInfo &getPrimaryBaseInfo() const {
+ /// getPrimaryBase - Get the primary base for this record.
+ const CXXRecordDecl *getPrimaryBase() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->PrimaryBase;
+ return CXXInfo->PrimaryBase.getPointer();
}
- // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
- const CXXRecordDecl *getPrimaryBase() const {
- return getPrimaryBaseInfo().getBase();
- }
+ /// isPrimaryBaseVirtual - Get whether the primary base for this record
+ /// is virtual or not.
+ bool isPrimaryBaseVirtual() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
- // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
- bool getPrimaryBaseWasVirtual() const {
- return getPrimaryBaseInfo().isVirtual();
+ return CXXInfo->PrimaryBase.getInt();
}
- /// getBaseClassOffset - Get the offset, in bits, for the given base class.
- uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
+ /// getBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits 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 {
+ /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits 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];
}
-
- uint64_t getSizeOfLargestEmptySubobject() const {
+
+ /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->SizeOfLargestEmptySubobject;
+ assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+
+ return getBaseClassOffset(Base).getQuantity() *
+ Base->getASTContext().getCharWidth();
}
- primary_base_info_iterator primary_base_begin() const {
+ /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
-
- return primary_base_info_iterator(getPrimaryBaseInfo());
+ assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
+
+ return getVBaseClassOffset(VBase).getQuantity() *
+ VBase->getASTContext().getCharWidth();
}
- primary_base_info_iterator primary_base_end() const {
+ CharUnits getSizeOfLargestEmptySubobject() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
-
- return primary_base_info_iterator();
+ return CXXInfo->SizeOfLargestEmptySubobject;
}
};
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 232e47b03ae5..921b799b94b5 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -143,6 +143,10 @@ public:
/// \brief Return whether this visitor should recurse into
/// template instantiations.
bool shouldVisitTemplateInstantiations() const { return false; }
+
+ /// \brief Return whether this visitor should recurse into the types of
+ /// TypeLocs.
+ bool shouldWalkTypesOfTypeLocs() const { return true; }
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
@@ -211,7 +215,7 @@ public:
/// be overridden for clients that need access to the name.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseConstructorInitializer(CXXBaseOrMemberInitializer *Init);
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
// ---- Methods on Stmts ----
@@ -368,7 +372,7 @@ private:
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D);
@@ -393,7 +397,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
- case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
+ case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
@@ -438,7 +442,8 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) \
- case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, T.getTypePtr());
+ case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \
+ const_cast<Type*>(T.getTypePtr()));
#include "clang/AST/TypeNodes.def"
}
@@ -531,7 +536,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
return getDerived().TraverseType(Arg.getAsType());
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(Arg.getAsExpr());
@@ -566,7 +573,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
}
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
@@ -592,7 +601,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
- CXXBaseOrMemberInitializer *Init) {
+ CXXCtorInitializer *Init) {
// FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()?
if (Init->isWritten())
TRY_TO(TraverseStmt(Init->getInit()));
@@ -706,10 +715,15 @@ DEF_TRAVERSE_TYPE(DecltypeType, {
TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPE(AutoType, {
+ TRY_TO(TraverseType(T->getDeducedType()));
+ })
+
DEF_TRAVERSE_TYPE(RecordType, { })
DEF_TRAVERSE_TYPE(EnumType, { })
DEF_TRAVERSE_TYPE(TemplateTypeParmType, { })
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { })
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
TRY_TO(TraverseTemplateName(T->getTemplateName()));
@@ -718,6 +732,14 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
+DEF_TRAVERSE_TYPE(AttributedType, {
+ TRY_TO(TraverseType(T->getModifiedType()));
+ })
+
+DEF_TRAVERSE_TYPE(ParenType, {
+ TRY_TO(TraverseType(T->getInnerType()));
+ })
+
DEF_TRAVERSE_TYPE(ElaboratedType, {
if (T->getQualifier()) {
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
@@ -734,6 +756,10 @@ DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
})
+DEF_TRAVERSE_TYPE(PackExpansionType, {
+ TRY_TO(TraverseType(T->getPattern()));
+ })
+
DEF_TRAVERSE_TYPE(ObjCInterfaceType, { })
DEF_TRAVERSE_TYPE(ObjCObjectType, {
@@ -752,14 +778,15 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
// ----------------- TypeLoc traversal -----------------
// This macro makes available a variable TL, the passed-in TypeLoc.
-// It calls WalkUpFrom* for the Type in the given TypeLoc, in addition
-// to WalkUpFrom* for the TypeLoc itself, such that existing clients
-// that override the WalkUpFrom*Type() and/or Visit*Type() methods
+// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
+// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
+// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
// continue to work.
#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
template<typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
- TRY_TO(WalkUpFrom##TYPE(TL.getTypePtr())); \
+ if (getDerived().shouldWalkTypesOfTypeLocs()) \
+ TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \
TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
{ CODE; } \
return true; \
@@ -867,22 +894,16 @@ DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, {
TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
})
-// FIXME: location of arguments, exception specifications (attributes?)
-// Note that we have the ParmVarDecl's here. Do we want to use them?
+// FIXME: location of exception specifications (attributes?)
DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
- FunctionProtoType *T = TL.getTypePtr();
-/*
+ const FunctionProtoType *T = TL.getTypePtr();
+
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
TRY_TO(TraverseDecl(TL.getArg(I)));
}
-*/
- for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
- AEnd = T->arg_type_end();
- A != AEnd; ++A) {
- TRY_TO(TraverseType(*A));
- }
+
for (FunctionProtoType::exception_iterator E = T->exception_begin(),
EEnd = T->exception_end();
E != EEnd; ++E) {
@@ -906,10 +927,15 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPELOC(AutoType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+ })
+
DEF_TRAVERSE_TYPELOC(RecordType, { })
DEF_TRAVERSE_TYPELOC(EnumType, { })
DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { })
// FIXME: use the loc for the template name?
DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
@@ -921,6 +947,14 @@ DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { })
+DEF_TRAVERSE_TYPELOC(ParenType, {
+ TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AttributedType, {
+ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
+ })
+
// FIXME: use the sourceloc on qualifier?
DEF_TRAVERSE_TYPELOC(ElaboratedType, {
if (TL.getTypePtr()->getQualifier()) {
@@ -941,6 +975,10 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
}
})
+DEF_TRAVERSE_TYPELOC(PackExpansionType, {
+ TRY_TO(TraverseTypeLoc(TL.getPatternLoc()));
+ })
+
DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { })
DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
@@ -1001,11 +1039,18 @@ DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
})
DEF_TRAVERSE_DECL(FriendDecl, {
- TRY_TO(TraverseDecl(D->getFriendDecl()));
+ // Friend is either decl or a type.
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
})
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
- TRY_TO(TraverseDecl(D->getFriendDecl()));
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
TemplateParameterList *TPL = D->getTemplateParameterList(I);
for (TemplateParameterList::iterator ITPL = TPL->begin(),
@@ -1051,6 +1096,11 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
return true;
})
+DEF_TRAVERSE_DECL(LabelDecl, {
+ // There is no code in a LabelDecl.
+})
+
+
DEF_TRAVERSE_DECL(NamespaceDecl, {
// Code in an unnamed namespace shows up automatically in
// decls_begin()/decls_end(). Thus we don't need to recurse on
@@ -1082,7 +1132,9 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
})
DEF_TRAVERSE_DECL(ObjCMethodDecl, {
- // FIXME: implement
+ // We don't traverse nodes in param_begin()/param_end(), as they
+ // appear in decls_begin()/decls_end() and thus are handled.
+ TRY_TO(TraverseStmt(D->getBody()));
})
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
@@ -1175,7 +1227,7 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
if (D->isThisDeclarationADefinition())
TRY_TO(TraverseClassInstantiations(D, D));
}
-
+
// Note that getInstantiatedFromMemberTemplate() is just a link
// from a template instantiation back to the template from which
// it was instantiated, and thus should not be traversed.
@@ -1208,10 +1260,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
assert(false && "Unknown specialization kind.");
}
}
-
+
return true;
}
-
+
DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
@@ -1251,7 +1303,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
})
DEF_TRAVERSE_DECL(TypedefDecl, {
- TRY_TO(TraverseType(D->getUnderlyingType()));
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the typedef, not something that was written in the
// source.
@@ -1282,11 +1334,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
RecordDecl *D) {
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the source.
- //
- // The anonymous struct or union object is the variable or field
- // whose type is the anonymous struct or union. We shouldn't
- // traverse D->getAnonymousStructOrUnionObject(), as it's not
- // something that is explicitly written in the source.
+
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
return true;
}
@@ -1380,6 +1428,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
})
+DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
+
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
@@ -1412,47 +1462,11 @@ template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
- // Visit the function type itself, which can be either
- // FunctionNoProtoType or FunctionProtoType, or a typedef. If it's
- // not a Function*ProtoType, then it can't have a body or arguments,
- // so we have to do less work.
- Type *FuncType = D->getType().getTypePtr();
- if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
- if (D->isThisDeclarationADefinition()) {
- // Don't call Traverse*, or the result type and parameter types
- // will be double counted.
- TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
- } else {
- // This works around a bug in Clang that does not add the parameters
- // to decls_begin/end for function declarations (as opposed to
- // definitions):
- // http://llvm.org/PR7442
- // We work around this here by traversing the function type.
- // This isn't perfect because we don't traverse the default
- // values, if any. It also may not interact great with
- // templates. But it's the best we can do until the bug is
- // fixed.
- // FIXME: replace the entire 'if' statement with
- // TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
- // when the bug is fixed.
- TRY_TO(TraverseFunctionProtoType(FuncProto));
- return true;
- }
- } else if (FunctionNoProtoType *FuncNoProto =
- dyn_cast<FunctionNoProtoType>(FuncType)) {
- // Don't call Traverse*, or the result type will be double
- // counted.
- TRY_TO(WalkUpFromFunctionNoProtoType(FuncNoProto));
- } else { // a typedef type, or who knows what
- assert(!D->isThisDeclarationADefinition() && "Unexpected function type");
- TRY_TO(TraverseType(D->getType()));
- return true;
- }
-
- TRY_TO(TraverseType(D->getResultType()));
-
// If we're an explicit template specialization, iterate over the
- // template args that were explicitly specified.
+ // template args that were explicitly specified. If we were doing
+ // this in typing order, we'd do it between the return type and
+ // the function args, but both are handled by the FunctionTypeLoc
+ // above, so we have to choose one side. I've decided to do before.
if (const FunctionTemplateSpecializationInfo *FTSI =
D->getTemplateSpecializationInfo()) {
if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
@@ -1467,28 +1481,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
}
- for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
-
- if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
- if (D->isThisDeclarationADefinition()) {
- // This would be visited if we called TraverseType(D->getType())
- // above, but we don't (at least, not in the
- // declaration-is-a-definition case), in order to avoid duplicate
- // visiting for parameters. (We need to check parameters here,
- // rather than letting D->getType() do it, so we visit default
- // parameter values). So we need to re-do some of the work the
- // type would do.
- for (FunctionProtoType::exception_iterator
- E = FuncProto->exception_begin(),
- EEnd = FuncProto->exception_end();
- E != EEnd; ++E) {
- TRY_TO(TraverseType(*E));
- }
- }
- }
+ // Visit the function type itself, which can be either
+ // FunctionNoProtoType or FunctionProtoType, or a typedef. This
+ // also covers the return type and the function parameters,
+ // including exception specifications.
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
@@ -1554,7 +1551,7 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseVarHelper(D));
+ TRY_TO(TraverseDeclaratorHelper(D));
TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
@@ -1577,12 +1574,11 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// ----------------- Stmt traversal -----------------
//
// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
-// over the children defined in child_begin/child_end (every stmt
-// defines these, though sometimes the range is empty). Each
-// individual Traverse* method only needs to worry about children
-// other than those. To see what child_begin()/end() does for a given
-// class, see, e.g.,
-// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
@@ -1590,9 +1586,8 @@ template<typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); \
- C != CEnd; ++C) { \
- TRY_TO(TraverseStmt(*C)); \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ TRY_TO(TraverseStmt(*range)); \
} \
return true; \
}
@@ -1608,12 +1603,12 @@ DEF_TRAVERSE_STMT(AsmStmt, {
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getClobber(I)));
}
- // child_begin()/end() iterates over inputExpr and outputExpr.
+ // children() iterates over inputExpr and outputExpr.
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
TRY_TO(TraverseDecl(S->getExceptionDecl()));
- // child_begin()/end() iterates over the handler block.
+ // children() iterates over the handler block.
})
DEF_TRAVERSE_STMT(DeclStmt, {
@@ -1621,11 +1616,11 @@ DEF_TRAVERSE_STMT(DeclStmt, {
I != E; ++I) {
TRY_TO(TraverseDecl(*I));
}
- // Suppress the default iteration over child_begin/end by
+ // Suppress the default iteration over children() by
// returning. Here's why: A DeclStmt looks like 'type var [=
// initializer]'. The decls above already traverse over the
// initializers, so we don't have to do it again (which
- // child_begin/end would do).
+ // children() would do).
return true;
})
@@ -1652,17 +1647,16 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { })
-DEF_TRAVERSE_STMT(SwitchCase, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(WhileStmt, { })
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
}
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(DeclRefExpr, {
@@ -1695,27 +1689,27 @@ DEF_TRAVERSE_STMT(ImplicitCastExpr, {
})
DEF_TRAVERSE_STMT(CStyleCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXConstCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
// InitListExpr is a tricky one, because we want to do all our work on
@@ -1729,9 +1723,8 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
S = Syn;
TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseStmt(*C));
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ TRY_TO(TraverseStmt(*range));
}
return true;
}
@@ -1739,12 +1732,12 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
// (i.e. non-class) type.
- if (!S->isImplicit())
- TRY_TO(TraverseType(S->getType()));
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXNewExpr, {
- TRY_TO(TraverseType(S->getAllocatedType()));
+ // The child-iterator will pick up the other arguments.
+ TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(OffsetOfExpr, {
@@ -1769,15 +1762,43 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
-DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
- TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc()));
- TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc()));
+DEF_TRAVERSE_STMT(CXXUuidofExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
- TRY_TO(TraverseType(S->getQueriedType()));
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
})
+DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
+ // This is called for code like 'return T()' where T is a class type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
+ // This is called for code like 'T()', where T is a template argument.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+// These expressions all might take explicit template arguments.
+// We traverse those if so. FIXME: implement these.
+DEF_TRAVERSE_STMT(CXXConstructExpr, { })
+DEF_TRAVERSE_STMT(CallExpr, { })
+DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
+
// These exprs (most of them), do not need any action except iterating
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1790,53 +1811,64 @@ DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
-DEF_TRAVERSE_STMT(CXXExprWithTemporaries, { })
+DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
-DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
+DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
+ TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
+ if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
+ TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
-DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
DEF_TRAVERSE_STMT(GNUNullExpr, { })
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
DEF_TRAVERSE_STMT(ObjCEncodeExpr, { })
-DEF_TRAVERSE_STMT(ObjCImplicitSetterGetterRefExpr, { })
DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
-DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
-DEF_TRAVERSE_STMT(VAArgExpr, {
- // The child-iterator will pick up the expression argument.
- TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
- })
-DEF_TRAVERSE_STMT(CXXConstructExpr, { })
-
-DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
- // This is called for code like 'return T()' where T is a class type.
- TRY_TO(TraverseType(S->getType()));
- })
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
-DEF_TRAVERSE_STMT(CallExpr, { })
-DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
+DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
+DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { })
// These operators (all of them) do not need any action except
// iterating over the children.
+DEF_TRAVERSE_STMT(BinaryConditionalOperator, { })
DEF_TRAVERSE_STMT(ConditionalOperator, { })
DEF_TRAVERSE_STMT(UnaryOperator, { })
DEF_TRAVERSE_STMT(BinaryOperator, { })
DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
+DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
+DEF_TRAVERSE_STMT(PackExpansionExpr, { })
+DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, { })
@@ -1861,7 +1893,6 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html
// Every class that has getQualifier.
#undef DEF_TRAVERSE_STMT
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index ba778293ba2d..e87ca78d635a 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -109,25 +109,7 @@ public:
/// \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. Make sure that this is actually the most recent
- // redeclaration, or we can build invalid chains. If the most recent
- // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
- RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
- PrevDecl->getMostRecentDeclaration()));
- 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));
- }
+ void setPreviousDeclaration(decl_type *PrevDecl);
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 62a6b6463df5..7ede9ce323f4 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -20,7 +20,6 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
-#include "clang/AST/FullExpr.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/ASTContext.h"
#include <string>
@@ -104,13 +103,7 @@ public:
first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class
#define ABSTRACT_STMT(STMT)
#include "clang/AST/StmtNodes.inc"
-};
-private:
- /// \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:
@@ -122,6 +115,77 @@ protected:
assert(0 && "Stmts cannot be released with regular 'delete'.");
}
+ class StmtBitfields {
+ friend class Stmt;
+
+ /// \brief The statement class.
+ unsigned sClass : 8;
+ };
+ enum { NumStmtBits = 8 };
+
+ class CompoundStmtBitfields {
+ friend class CompoundStmt;
+ unsigned : NumStmtBits;
+
+ unsigned NumStmts : 32 - NumStmtBits;
+ };
+
+ class ExprBitfields {
+ friend class Expr;
+ friend class DeclRefExpr; // computeDependence
+ friend class InitListExpr; // ctor
+ friend class DesignatedInitExpr; // ctor
+ friend class BlockDeclRefExpr; // ctor
+ friend class ASTStmtReader; // deserialization
+ friend class CXXNewExpr; // ctor
+ friend class DependentScopeDeclRefExpr; // ctor
+ friend class CXXConstructExpr; // ctor
+ friend class CallExpr; // ctor
+ friend class OffsetOfExpr; // ctor
+ friend class ObjCMessageExpr; // ctor
+ friend class ShuffleVectorExpr; // ctor
+ friend class ParenListExpr; // ctor
+ friend class CXXUnresolvedConstructExpr; // ctor
+ friend class CXXDependentScopeMemberExpr; // ctor
+ friend class OverloadExpr; // ctor
+ unsigned : NumStmtBits;
+
+ unsigned ValueKind : 2;
+ unsigned ObjectKind : 2;
+ unsigned TypeDependent : 1;
+ unsigned ValueDependent : 1;
+ unsigned ContainsUnexpandedParameterPack : 1;
+ };
+ enum { NumExprBits = 15 };
+
+ class CastExprBitfields {
+ friend class CastExpr;
+ unsigned : NumExprBits;
+
+ unsigned Kind : 6;
+ unsigned BasePathSize : 32 - 6 - NumExprBits;
+ };
+
+ class CallExprBitfields {
+ friend class CallExpr;
+ unsigned : NumExprBits;
+
+ unsigned NumPreArgs : 1;
+ };
+
+ union {
+ // FIXME: this is wasteful on 64-bit platforms.
+ void *Aligner;
+
+ StmtBitfields StmtBits;
+ CompoundStmtBitfields CompoundStmtBits;
+ ExprBitfields ExprBits;
+ CastExprBitfields CastExprBits;
+ CallExprBitfields CallExprBits;
+ };
+
+ friend class ASTStmtReader;
+
public:
// Only allow allocation of Stmts using the allocator in ASTContext
// or by doing a placement new.
@@ -152,44 +216,27 @@ public:
protected:
/// \brief Construct an empty statement.
- explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
+ explicit Stmt(StmtClass SC, EmptyShell) {
+ StmtBits.sClass = SC;
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
public:
- Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
+ Stmt(StmtClass SC) {
+ StmtBits.sClass = SC;
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
- virtual ~Stmt() {}
-
-#ifndef NDEBUG
- /// \brief True if this statement's refcount is in a valid state.
- /// Should be used only in assertions.
- bool isRetained() const {
- return (RefCount >= 1);
- }
-#endif
-
- /// \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;
+ return static_cast<StmtClass>(StmtBits.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.
- virtual SourceRange getSourceRange() const = 0;
+ SourceRange getSourceRange() const;
+
SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
@@ -236,22 +283,25 @@ public:
/// within CFGs.
bool hasImplicitControlFlow() const;
- /// Child Iterators: All subclasses must implement child_begin and child_end
- /// to permit easy iteration over the substatements/subexpessions of an
- /// AST node. This permits easy iteration over all nodes in the AST.
+ /// Child Iterators: All subclasses must implement 'children'
+ /// to permit easy iteration over the substatements/subexpessions of an
+ /// 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;
+ typedef StmtRange child_range;
+ typedef ConstStmtRange const_child_range;
- const_child_iterator child_begin() const {
- return const_child_iterator(const_cast<Stmt*>(this)->child_begin());
+ child_range children();
+ const_child_range children() const {
+ return const_cast<Stmt*>(this)->children();
}
- const_child_iterator child_end() const {
- return const_child_iterator(const_cast<Stmt*>(this)->child_end());
- }
+ child_iterator child_begin() { return children().first; }
+ child_iterator child_end() { return children().second; }
+
+ const_child_iterator child_begin() const { return children().first; }
+ const_child_iterator child_end() const { return children().second; }
/// \brief Produce a unique representation of the given statement.
///
@@ -265,7 +315,7 @@ public:
/// 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,
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
bool Canonical);
};
@@ -314,8 +364,10 @@ public:
static bool classof(const DeclStmt *) { return true; }
// Iterators over subexpressions.
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(child_iterator(DG.begin(), DG.end()),
+ child_iterator(DG.end(), DG.end()));
+ }
typedef DeclGroupRef::iterator decl_iterator;
typedef DeclGroupRef::const_iterator const_decl_iterator;
@@ -330,8 +382,16 @@ public:
///
class NullStmt : public Stmt {
SourceLocation SemiLoc;
+
+ /// \brief Whether the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ bool LeadingEmptyMacro;
public:
- NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
+ NullStmt(SourceLocation L, bool LeadingEmptyMacro = false)
+ : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {}
/// \brief Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
@@ -339,55 +399,66 @@ public:
SourceLocation getSemiLoc() const { return SemiLoc; }
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
+ bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; }
+
+ SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
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();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// CompoundStmt - This represents a group of statements like { stmt stmt }.
///
class CompoundStmt : public Stmt {
Stmt** Body;
- unsigned NumStmts;
SourceLocation LBracLoc, RBracLoc;
public:
- CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
- SourceLocation LB, SourceLocation RB)
- : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) {
+ CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts,
+ SourceLocation LB, SourceLocation RB)
+ : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
+ CompoundStmtBits.NumStmts = NumStmts;
+
if (NumStmts == 0) {
Body = 0;
return;
}
Body = new (C) Stmt*[NumStmts];
- memcpy(Body, StmtStart, numStmts * sizeof(*Body));
+ memcpy(Body, StmtStart, NumStmts * sizeof(*Body));
}
// \brief Build an empty compound statement.
explicit CompoundStmt(EmptyShell Empty)
- : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
+ : Stmt(CompoundStmtClass, Empty), Body(0) {
+ CompoundStmtBits.NumStmts = 0;
+ }
void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
- bool body_empty() const { return NumStmts == 0; }
- unsigned size() const { return NumStmts; }
+ bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
+ unsigned size() const { return CompoundStmtBits.NumStmts; }
typedef Stmt** body_iterator;
body_iterator body_begin() { return Body; }
- body_iterator body_end() { return Body + NumStmts; }
- Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; }
+ body_iterator body_end() { return Body + size(); }
+ Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; }
+
+ void setLastStmt(Stmt *S) {
+ assert(!body_empty() && "setLastStmt");
+ Body[size()-1] = S;
+ }
typedef Stmt* const * const_body_iterator;
const_body_iterator body_begin() const { return Body; }
- const_body_iterator body_end() const { return Body + NumStmts; }
- const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; }
+ const_body_iterator body_end() const { return Body + size(); }
+ const Stmt *body_back() const { return !body_empty() ? Body[size()-1] : 0; }
typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
reverse_body_iterator body_rbegin() {
@@ -408,7 +479,7 @@ public:
return const_reverse_body_iterator(body_begin());
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
}
@@ -423,8 +494,9 @@ public:
static bool classof(const CompoundStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
+ }
};
// SwitchCase is the base class for CaseStmt and DefaultStmt,
@@ -443,17 +515,15 @@ public:
void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
- Stmt *getSubStmt() { return v_getSubStmt(); }
+ Stmt *getSubStmt();
- virtual SourceRange getSourceRange() const { return SourceRange(); }
+ SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CaseStmtClass ||
- T->getStmtClass() == DefaultStmtClass;
+ T->getStmtClass() == DefaultStmtClass;
}
static bool classof(const SwitchCase *) { return true; }
-protected:
- virtual Stmt* v_getSubStmt() = 0;
};
class CaseStmt : public SwitchCase {
@@ -463,8 +533,6 @@ class CaseStmt : public SwitchCase {
SourceLocation CaseLoc;
SourceLocation EllipsisLoc;
SourceLocation ColonLoc;
-
- virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
@@ -504,7 +572,7 @@ public:
void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
- virtual SourceRange getSourceRange() const {
+ 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()))
@@ -518,15 +586,15 @@ public:
static bool classof(const CaseStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
};
class DefaultStmt : public SwitchCase {
Stmt* SubStmt;
SourceLocation DefaultLoc;
SourceLocation ColonLoc;
- virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
@@ -544,7 +612,7 @@ public:
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(DefaultLoc, SubStmt->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -553,42 +621,43 @@ public:
static bool classof(const DefaultStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
+
+/// LabelStmt - Represents a label, which has a substatement. For example:
+/// foo: return;
+///
class LabelStmt : public Stmt {
- IdentifierInfo *Label;
+ LabelDecl *TheDecl;
Stmt *SubStmt;
SourceLocation IdentLoc;
public:
- LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
- : Stmt(LabelStmtClass), Label(label),
- SubStmt(substmt), IdentLoc(IL) {}
+ LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
+ : Stmt(LabelStmtClass), TheDecl(D), 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; }
+ LabelDecl *getDecl() const { return TheDecl; }
+ void setDecl(LabelDecl *D) { TheDecl = D; }
const char *getName() const;
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
void setIdentLoc(SourceLocation L) { IdentLoc = L; }
void setSubStmt(Stmt *SS) { SubStmt = SS; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(IdentLoc, SubStmt->getLocEnd());
}
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+
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();
};
@@ -635,22 +704,23 @@ public:
SourceLocation getElseLoc() const { return ElseLoc; }
void setElseLoc(SourceLocation L) { ElseLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (SubExprs[ELSE])
return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
else
return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
}
+ // Iterators over subexpressions. The iterators will include iterating
+ // over the initialization expression referenced by the condition variable.
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == IfStmtClass;
}
static bool classof(const IfStmt *) { return true; }
-
- // Iterators over subexpressions. The iterators will include iterating
- // over the initialization expression referenced by the condition variable.
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
};
/// SwitchStmt - This represents a 'switch' stmt.
@@ -662,6 +732,11 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
+ /// If the SwitchStmt is a switch on an enum value, this records whether
+ /// all the enum values were covered by CaseStmts. This value is meant to
+ /// be a hint for possible clients.
+ unsigned AllEnumCasesCovered : 1;
+
public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@@ -705,21 +780,34 @@ public:
}
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 {
+
+ /// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
+ /// switch over an enum value then all cases have been explicitly covered.
+ void setAllEnumCasesCovered() {
+ AllEnumCasesCovered = 1;
+ }
+
+ /// Returns true if the SwitchStmt is a switch of an enum value and all cases
+ /// have been explicitly covered.
+ bool isAllEnumCasesCovered() const {
+ return (bool) AllEnumCasesCovered;
+ }
+
+ SourceRange getSourceRange() const {
return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
}
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
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();
};
@@ -757,7 +845,7 @@ public:
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -766,14 +854,15 @@ public:
static bool classof(const WhileStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// DoStmt - This represents a 'do/while' stmt.
///
class DoStmt : public Stmt {
- enum { COND, BODY, END_EXPR };
+ enum { BODY, COND, END_EXPR };
Stmt* SubExprs[END_EXPR];
SourceLocation DoLoc;
SourceLocation WhileLoc;
@@ -805,7 +894,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(DoLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -814,8 +903,9 @@ public:
static bool classof(const DoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
@@ -870,7 +960,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -879,32 +969,33 @@ public:
static bool classof(const ForStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// GotoStmt - This represents a direct goto.
///
class GotoStmt : public Stmt {
- LabelStmt *Label;
+ LabelDecl *Label;
SourceLocation GotoLoc;
SourceLocation LabelLoc;
public:
- GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
+ GotoStmt(LabelDecl *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) { }
- LabelStmt *getLabel() const { return Label; }
- void setLabel(LabelStmt *S) { Label = S; }
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *D) { Label = D; }
SourceLocation getGotoLoc() const { return GotoLoc; }
void setGotoLoc(SourceLocation L) { GotoLoc = L; }
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(GotoLoc, LabelLoc);
}
static bool classof(const Stmt *T) {
@@ -913,8 +1004,7 @@ public:
static bool classof(const GotoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// IndirectGotoStmt - This represents an indirect goto.
@@ -938,11 +1028,18 @@ public:
void setStarLoc(SourceLocation L) { StarLoc = L; }
SourceLocation getStarLoc() const { return StarLoc; }
- Expr *getTarget();
- const Expr *getTarget() const;
+ Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
+ const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
- virtual SourceRange getSourceRange() const {
+ /// getConstantTarget - Returns the fixed target of this indirect
+ /// goto, if one exists.
+ LabelDecl *getConstantTarget();
+ const LabelDecl *getConstantTarget() const {
+ return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+ }
+
+ SourceRange getSourceRange() const {
return SourceRange(GotoLoc, Target->getLocEnd());
}
@@ -952,8 +1049,7 @@ public:
static bool classof(const IndirectGotoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Target, &Target+1); }
};
@@ -970,7 +1066,7 @@ public:
SourceLocation getContinueLoc() const { return ContinueLoc; }
void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ContinueLoc);
}
@@ -980,8 +1076,7 @@ public:
static bool classof(const ContinueStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// BreakStmt - This represents a break.
@@ -997,7 +1092,7 @@ public:
SourceLocation getBreakLoc() const { return BreakLoc; }
void setBreakLoc(SourceLocation L) { BreakLoc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
+ SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BreakStmtClass;
@@ -1005,8 +1100,7 @@ public:
static bool classof(const BreakStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
@@ -1050,7 +1144,7 @@ public:
const VarDecl *getNRVOCandidate() const { return NRVOCandidate; }
void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ReturnStmtClass;
@@ -1058,8 +1152,10 @@ public:
static bool classof(const ReturnStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ return child_range();
+ }
};
/// AsmStmt - This represents a GNU inline-assembly statement extension.
@@ -1257,7 +1353,7 @@ public:
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AsmLoc, RParenLoc);
}
@@ -1304,10 +1400,9 @@ public:
return &Exprs[0] + NumOutputs;
}
- // Child iterators
-
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs);
+ }
};
} // end namespace clang
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 0508f35e48e8..f08815fd562d 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -37,7 +37,7 @@ public:
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
@@ -51,8 +51,7 @@ public:
}
static bool classof(const CXXCatchStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
friend class ASTStmtReader;
};
@@ -84,7 +83,7 @@ public:
static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getTryLoc(), getEndLoc());
}
@@ -113,8 +112,9 @@ public:
}
static bool classof(const CXXTryStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
+ }
friend class ASTStmtReader;
};
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 4da2e3474b1c..851c001adc54 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -1,4 +1,4 @@
-//===--- StmtIterator.h - Iterators for Statements ------------------------===//
+//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -51,11 +51,11 @@ protected:
return (RawVAPtr & Flags) == 0;
}
- VariableArrayType* getVAPtr() const {
- return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
+ const VariableArrayType *getVAPtr() const {
+ return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
}
- void setVAPtr(VariableArrayType* P) {
+ void setVAPtr(const VariableArrayType *P) {
assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
@@ -68,7 +68,7 @@ protected:
StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
StmtIteratorBase(Decl *d, Stmt **s);
- StmtIteratorBase(VariableArrayType *t);
+ StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
};
@@ -86,7 +86,7 @@ public:
StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
- StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
+ StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
if (inDecl() || inDeclGroup()) {
@@ -130,7 +130,7 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
StmtIterator(Decl** dgi, Decl** dge)
: StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
- StmtIterator(VariableArrayType* t)
+ StmtIterator(const VariableArrayType *t)
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(Decl* D, Stmt **s = 0)
@@ -146,6 +146,86 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
+/// A range of statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (StmtRange range = stmt->children(); range; ++range)
+struct StmtRange : std::pair<StmtIterator,StmtIterator> {
+ StmtRange() {}
+ StmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<StmtIterator,StmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ Stmt *operator->() const { return first.operator->(); }
+ Stmt *&operator*() const { return first.operator*(); }
+
+ StmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ StmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ StmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const StmtIterator &begin(const StmtRange &range) {
+ return range.first;
+ }
+ friend const StmtIterator &end(const StmtRange &range) {
+ return range.second;
+ }
+};
+
+/// A range of const statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (ConstStmtRange range = stmt->children(); range; ++range)
+struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
+ ConstStmtRange() {}
+ ConstStmtRange(const ConstStmtIterator &begin,
+ const ConstStmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+ ConstStmtRange(const StmtRange &range)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
+ {}
+ ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ const Stmt *operator->() const { return first.operator->(); }
+ const Stmt *operator*() const { return first.operator*(); }
+
+ ConstStmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ ConstStmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ ConstStmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
+ return range.first;
+ }
+ friend const ConstStmtIterator &end(const ConstStmtRange &range) {
+ return range.second;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index 269aa4c6dab2..1800a71f9154 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -55,7 +55,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -64,8 +64,9 @@ public:
static bool classof(const ObjCForCollectionStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
};
/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
@@ -102,7 +103,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtCatchLoc, Body->getLocEnd());
}
@@ -113,8 +114,7 @@ public:
}
static bool classof(const ObjCAtCatchStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Body, &Body + 1); }
};
/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
@@ -133,7 +133,7 @@ public:
Stmt *getFinallyBody() { return AtFinallyStmt; }
void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
}
@@ -145,8 +145,9 @@ public:
}
static bool classof(const ObjCAtFinallyStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
+ }
};
/// ObjCAtTryStmt - This represent objective-c's over-all
@@ -239,15 +240,17 @@ public:
getStmts()[1 + NumCatchStmts] = S;
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
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();
+ child_range children() {
+ return child_range(getStmts(),
+ getStmts() + 1 + NumCatchStmts + HasFinally);
+ }
};
/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
@@ -291,7 +294,7 @@ public:
}
void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
}
@@ -300,8 +303,9 @@ public:
}
static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
+ }
};
/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
@@ -323,7 +327,7 @@ public:
SourceLocation getThrowLoc() { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (Throw)
return SourceRange(AtThrowLoc, Throw->getLocEnd());
else
@@ -335,8 +339,7 @@ public:
}
static bool classof(const ObjCAtThrowStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Throw, &Throw+1); }
};
} // end namespace clang
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 7d5123fb0449..a4e074e083f6 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -23,6 +23,7 @@
namespace llvm {
class FoldingSetNodeID;
+ class raw_ostream;
}
namespace clang {
@@ -30,26 +31,14 @@ namespace clang {
class Decl;
class DiagnosticBuilder;
class Expr;
+struct PrintingPolicy;
class TypeSourceInfo;
/// \brief Represents a template argument within a class template
/// specialization.
class TemplateArgument {
- union {
- uintptr_t TypeOrValue;
- struct {
- char Value[sizeof(llvm::APSInt)];
- void *Type;
- } Integer;
- struct {
- TemplateArgument *Args;
- unsigned NumArgs;
- bool CopyArgs;
- } Args;
- };
-
public:
- /// \brief The type of template argument we're storing.
+ /// \brief The kind of template argument we're storing.
enum ArgKind {
/// \brief Represents an empty template argument, e.g., one that has not
/// been deduced.
@@ -66,16 +55,42 @@ public:
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
+ /// The template argument is a pack expansion of a template name that was
+ /// provided for a template template parameter.
+ TemplateExpansion,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack
- } Kind;
+ };
+
+private:
+ /// \brief The kind of template argument we're storing.
+ unsigned Kind;
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ } Args;
+ struct {
+ void *Name;
+ unsigned NumExpansions;
+ } TemplateArg;
+ };
+
+ TemplateArgument(TemplateName, bool); // DO NOT USE
+
+public:
/// \brief Construct an empty, invalid template argument.
- TemplateArgument() : TypeOrValue(0), Kind(Null) { }
+ TemplateArgument() : Kind(Null), TypeOrValue(0) { }
/// \brief Construct a template type argument.
TemplateArgument(QualType T) : Kind(Type) {
@@ -92,6 +107,8 @@ public:
/// \brief Construct an integral constant template argument.
TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
new (Integer.Value) llvm::APSInt(Value);
Integer.Type = Type.getAsOpaquePtr();
}
@@ -102,10 +119,35 @@ public:
/// parameters. However, the template name could be a dependent template
/// name that ends up being instantiated to a function template whose address
/// is taken.
- TemplateArgument(TemplateName Name) : Kind(Template) {
- TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ ///
+ /// \param Name The template name.
+ TemplateArgument(TemplateName Name) : Kind(Template)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ TemplateArg.NumExpansions = 0;
}
-
+
+ /// \brief Construct a template argument that is a template pack expansion.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ ///
+ /// \param Name The template name.
+ ///
+ /// \param NumExpansions The number of expansions that will be generated by
+ /// instantiating
+ TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
+ : Kind(TemplateExpansion)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ if (NumExpansions)
+ TemplateArg.NumExpansions = *NumExpansions + 1;
+ else
+ TemplateArg.NumExpansions = 0;
+ }
+
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
@@ -115,46 +157,59 @@ public:
TypeOrValue = reinterpret_cast<uintptr_t>(E);
}
+ /// \brief Construct a template argument that is a template argument pack.
+ ///
+ /// We assume that storage for the template arguments provided
+ /// outlives the TemplateArgument itself.
+ TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
+ this->Args.Args = Args;
+ this->Args.NumArgs = NumArgs;
+ }
+
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
if (Kind == Integral) {
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
- Args.Args = new TemplateArgument[Args.NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = Other.Args.Args[I];
- }
- else
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else
TypeOrValue = Other.TypeOrValue;
}
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;
- } else {
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
+ return *this;
+ }
+
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
- Kind = Other.Kind;
+ Kind = Other.Kind;
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else
- TypeOrValue = Other.TypeOrValue;
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Other.Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else {
+ TypeOrValue = Other.TypeOrValue;
}
return *this;
@@ -165,16 +220,31 @@ public:
if (Kind == Integral)
getAsIntegral()->~APSInt();
- else if (Kind == Pack && Args.CopyArgs)
- delete[] Args.Args;
}
+ /// \brief Create a new template argument pack by copying the given set of
+ /// template arguments.
+ static TemplateArgument CreatePackCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
/// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return Kind; }
+ ArgKind getKind() const { return (ArgKind)Kind; }
/// \brief Determine whether this template argument has no value.
bool isNull() const { return Kind == Null; }
+ /// \brief Whether this template argument is dependent on a template
+ /// parameter.
+ bool isDependent() const;
+
+ /// \brief Whether this template argument contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Determine whether this template argument is a pack expansion.
+ bool isPackExpansion() const;
+
/// \brief Retrieve the template argument as a type.
QualType getAsType() const {
if (Kind != Type)
@@ -195,9 +265,21 @@ public:
if (Kind != Template)
return TemplateName();
- return TemplateName::getFromVoidPointer(
- reinterpret_cast<void *> (TypeOrValue));
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
+ }
+
+ /// \brief Retrieve the template argument as a template name; if the argument
+ /// is a pack expansion, return the pattern as a template name.
+ TemplateName getAsTemplateOrTemplatePattern() const {
+ if (Kind != Template && Kind != TemplateExpansion)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
+
+ /// \brief Retrieve the number of expansions that a template template argument
+ /// expansion will produce, if known.
+ llvm::Optional<unsigned> getNumTemplateExpansions() const;
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
@@ -260,11 +342,17 @@ public:
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;
- /// \brief Construct a template argument pack.
- void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ TemplateArgument getPackExpansionPattern() const;
+ /// \brief Print this template argument to the given output stream.
+ void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
+
/// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
};
/// Location information for a TemplateArgument.
@@ -276,95 +364,48 @@ private:
struct {
unsigned QualifierRange[2];
unsigned TemplateNameLoc;
+ unsigned EllipsisLoc;
} Template;
};
-#ifndef NDEBUG
- enum Kind {
- K_None,
- K_TypeSourceInfo,
- K_Expression,
- K_Template
- } Kind;
-#endif
-
public:
- TemplateArgumentLocInfo()
- : Expression(0)
-#ifndef NDEBUG
- , Kind(K_None)
-#endif
- {}
+ TemplateArgumentLocInfo();
- TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
- : Declarator(TInfo)
-#ifndef NDEBUG
- , Kind(K_TypeSourceInfo)
-#endif
- {}
+ TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
- TemplateArgumentLocInfo(Expr *E)
- : Expression(E)
-#ifndef NDEBUG
- , Kind(K_Expression)
-#endif
- {}
+ TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
TemplateArgumentLocInfo(SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
-#ifndef NDEBUG
- : Kind(K_Template)
-#endif
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
{
Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
}
TypeSourceInfo *getAsTypeSourceInfo() const {
- assert(Kind == K_TypeSourceInfo);
return Declarator;
}
Expr *getAsExpr() const {
- assert(Kind == K_Expression);
return Expression;
}
SourceRange getTemplateQualifierRange() const {
- assert(Kind == K_Template);
return SourceRange(
SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
}
SourceLocation getTemplateNameLoc() const {
- assert(Kind == K_Template);
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
}
-#ifndef NDEBUG
- void validateForArgument(const TemplateArgument &Arg) {
- switch (Arg.getKind()) {
- case TemplateArgument::Type:
- assert(Kind == K_TypeSourceInfo);
- break;
- case TemplateArgument::Expression:
- case TemplateArgument::Declaration:
- assert(Kind == K_Expression);
- break;
- case TemplateArgument::Template:
- assert(Kind == K_Template);
- break;
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- assert(Kind == K_None);
- break;
- case TemplateArgument::Null:
- llvm_unreachable("source info for null template argument?");
- }
+ SourceLocation getTemplateEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
}
-#endif
};
/// Location wrapper for a TemplateArgument. TemplateArgument is to
@@ -393,14 +434,18 @@ public:
TemplateArgumentLoc(const TemplateArgument &Argument,
SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
- : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
- assert(Argument.getKind() == TemplateArgument::Template);
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc = SourceLocation())
+ : Argument(Argument),
+ LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
}
/// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
- if (Argument.getKind() == TemplateArgument::Template)
+ if (Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
return getSourceRange().getBegin();
@@ -433,14 +478,32 @@ public:
}
SourceRange getTemplateQualifierRange() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierRange();
}
SourceLocation getTemplateNameLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
}
+
+ SourceLocation getTemplateEllipsisLoc() const {
+ assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateEllipsisLoc();
+ }
+
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ ///
+ /// \param NumExpansions Will be set to the number of expansions that will
+ /// be generated from this pack expansion, if known a priori.
+ TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
+ ASTContext &Context) const;
};
/// A convenient class for passing around template argument
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index ddfac712734b..1721973e8229 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -23,43 +23,119 @@ namespace llvm {
}
namespace clang {
-
+
+class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
class IdentifierInfo;
class NestedNameSpecifier;
+class OverloadedTemplateStorage;
struct PrintingPolicy;
class QualifiedTemplateName;
class NamedDecl;
+class SubstTemplateTemplateParmPackStorage;
+class TemplateArgument;
class TemplateDecl;
-
-/// \brief A structure for storing the information associated with an
-/// overloaded template name.
-class OverloadedTemplateStorage {
+class TemplateTemplateParmDecl;
+
+/// \brief Implementation class used to describe either a set of overloaded
+/// template names or an already-substituted template template parameter pack.
+class UncommonTemplateNameStorage {
+protected:
union {
- unsigned Size;
- NamedDecl *Storage[1];
+ struct {
+ /// \brief If true, this is an OverloadedTemplateStorage instance;
+ /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance.
+ unsigned IsOverloadedStorage : 1;
+
+ /// \brief The number of stored templates or template arguments,
+ /// depending on which subclass we have.
+ unsigned Size : 31;
+ } Bits;
+
+ void *PointerAlignment;
};
-
+
+ UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) {
+ Bits.IsOverloadedStorage = OverloadedStorage;
+ Bits.Size = Size;
+ }
+
+public:
+ unsigned size() const { return Bits.Size; }
+
+ OverloadedTemplateStorage *getAsOverloadedStorage() {
+ return Bits.IsOverloadedStorage
+ ? reinterpret_cast<OverloadedTemplateStorage *>(this)
+ : 0;
+ }
+
+ SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
+ return Bits.IsOverloadedStorage
+ ? 0
+ : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ;
+ }
+};
+
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
- OverloadedTemplateStorage(unsigned Size) : Size(Size) {}
+ OverloadedTemplateStorage(unsigned Size)
+ : UncommonTemplateNameStorage(Size, true) { }
NamedDecl **getStorage() {
- return &Storage[1];
+ return reinterpret_cast<NamedDecl **>(this + 1);
}
NamedDecl * const *getStorage() const {
- return &Storage[1];
+ return reinterpret_cast<NamedDecl *const *>(this + 1);
}
public:
typedef NamedDecl *const *iterator;
- unsigned size() const { return Size; }
-
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
};
+
+
+/// \brief A structure for storing an already-substituted template template
+/// parameter pack.
+///
+/// This kind of template names occurs when the parameter pack has been
+/// provided with a template template argument pack in a context where its
+/// enclosing pack expansion could not be fully expanded.
+class SubstTemplateTemplateParmPackStorage
+ : public UncommonTemplateNameStorage, public llvm::FoldingSetNode
+{
+ ASTContext &Context;
+ TemplateTemplateParmDecl *Parameter;
+ const TemplateArgument *Arguments;
+
+public:
+ SubstTemplateTemplateParmPackStorage(ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ unsigned Size,
+ const TemplateArgument *Arguments)
+ : UncommonTemplateNameStorage(Size, false), Context(Context),
+ Parameter(Parameter), Arguments(Arguments) { }
+
+ /// \brief Retrieve the template template parameter pack being substituted.
+ TemplateTemplateParmDecl *getParameterPack() const {
+ return Parameter;
+ }
+
+ /// \brief Retrieve the template template argument pack with which this
+ /// parameter was substituted.
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ const TemplateArgument &ArgPack);
+};
/// \brief Represents a C++ template name within the type system.
///
@@ -90,7 +166,7 @@ public:
/// only be understood in the context of
class TemplateName {
typedef llvm::PointerUnion4<TemplateDecl *,
- OverloadedTemplateStorage *,
+ UncommonTemplateNameStorage *,
QualifiedTemplateName *,
DependentTemplateName *> StorageType;
@@ -103,16 +179,28 @@ class TemplateName {
public:
// \brief Kind of name that is actually stored.
enum NameKind {
+ /// \brief A single template declaration.
Template,
+ /// \brief A set of overloaded template declarations.
OverloadedTemplate,
+ /// \brief A qualified template name, where the qualification is kept
+ /// to describe the source code as written.
QualifiedTemplate,
- DependentTemplate
+ /// \brief A dependent template name that has not been resolved to a
+ /// template (or set of templates).
+ DependentTemplate,
+ /// \brief A template template parameter pack that has been substituted for
+ /// a template template argument pack, but has not yet been expanded into
+ /// individual arguments.
+ SubstTemplateTemplateParmPack
};
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
explicit TemplateName(OverloadedTemplateStorage *Storage)
: Storage(Storage) { }
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
+ : Storage(Storage) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
@@ -122,7 +210,7 @@ public:
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
- /// \brief Retrieve the the underlying template declaration that
+ /// \brief Retrieve the underlying template declaration that
/// this template name refers to, if known.
///
/// \returns The template declaration that this template name refers
@@ -131,7 +219,7 @@ public:
/// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
- /// \brief Retrieve the the underlying, overloaded function template
+ /// \brief Retrieve the underlying, overloaded function template
// declarations that this template name refers to, if known.
///
/// \returns The set of overloaded function templates that this template
@@ -139,7 +227,25 @@ public:
/// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL.
OverloadedTemplateStorage *getAsOverloadedTemplate() const {
- return Storage.dyn_cast<OverloadedTemplateStorage *>();
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsOverloadedStorage();
+
+ return 0;
+ }
+
+ /// \brief Retrieve the substituted template template parameter pack, if
+ /// known.
+ ///
+ /// \returns The storage for the substituted template template parameter pack,
+ /// if known. Otherwise, returns NULL.
+ SubstTemplateTemplateParmPackStorage *
+ getAsSubstTemplateTemplateParmPack() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsSubstTemplateTemplateParmPack();
+
+ return 0;
}
/// \brief Retrieve the underlying qualified template name
@@ -157,6 +263,10 @@ public:
/// \brief Determines whether this is a dependent template name.
bool isDependent() const;
+ /// \brief Determines whether this template name contains an
+ /// unexpanded parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
/// \brief Print the template name.
///
/// \param OS the output stream to which the template name will be
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 92e62a58d42c..9b177cceed96 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -18,12 +18,14 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Visibility.h"
#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/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
@@ -34,7 +36,7 @@ using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
namespace clang {
enum {
- TypeAlignmentInBits = 3,
+ TypeAlignmentInBits = 4,
TypeAlignment = 1 << TypeAlignmentInBits
};
class Type;
@@ -91,8 +93,9 @@ namespace clang {
class TemplateArgument;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
- class Type;
class ElaboratedType;
+ class ExtQuals;
+ class ExtQualsTypeCommonBase;
struct PrintingPolicy;
template <typename> class CanQual;
@@ -128,7 +131,7 @@ public:
MaxAddressSpace = 0xffffffu,
/// The width of the "fast" qualifier mask.
- FastWidth = 2,
+ FastWidth = 3,
/// The fast qualifier mask.
FastMask = (1 << FastWidth) - 1
@@ -271,6 +274,25 @@ public:
}
}
+ /// \brief Add the qualifiers from the given set to this set, given that
+ /// they don't conflict.
+ void addConsistentQualifiers(Qualifiers qs) {
+ assert(getAddressSpace() == qs.getAddressSpace() ||
+ !hasAddressSpace() || !qs.hasAddressSpace());
+ assert(getObjCGCAttr() == qs.getObjCGCAttr() ||
+ !hasObjCGCAttr() || !qs.hasObjCGCAttr());
+ Mask |= qs.Mask;
+ }
+
+ /// \brief Determines if these qualifiers compatibly include another set.
+ /// Generally this answers the question of whether an object with the other
+ /// qualifiers can be safely used as an object with these qualifiers.
+ bool compatiblyIncludes(Qualifiers other) const {
+ // Non-CVR qualifiers must match exactly. CVR qualifiers may subset.
+ return ((Mask & ~CVRMask) == (other.Mask & ~CVRMask)) &&
+ (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+ }
+
bool isSupersetOf(Qualifiers Other) const;
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
@@ -325,85 +347,6 @@ private:
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);
- }
-};
-
/// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_Default,
@@ -414,6 +357,7 @@ enum CallingConv {
CC_X86Pascal // __attribute__((pascal))
};
+typedef std::pair<const Type*, Qualifiers> SplitQualType;
/// 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
@@ -440,8 +384,14 @@ class QualType {
return Value.getPointer().get<const Type*>();
}
- QualType getUnqualifiedTypeSlow() const;
-
+ const ExtQualsTypeCommonBase *getCommonPtr() const {
+ assert(!isNull() && "Cannot retrieve a NULL type pointer");
+ uintptr_t CommonPtrVal
+ = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
+ CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
+ return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
+ }
+
friend class QualifierCollector;
public:
QualType() {}
@@ -457,24 +407,29 @@ public:
/// 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 (hasLocalNonFastQualifiers())
- return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
- return const_cast<Type*>(getTypePtrUnsafe());
- }
+ ///
+ /// This function requires that the type not be NULL. If the type might be
+ /// NULL, use the (slightly less efficient) \c getTypePtrOrNull().
+ const Type *getTypePtr() const;
+
+ const Type *getTypePtrOrNull() const;
+
+ /// Divides a QualType into its unqualified type and a set of local
+ /// qualifiers.
+ SplitQualType split() const;
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
- static QualType getFromOpaquePtr(void *Ptr) {
+ static QualType getFromOpaquePtr(const void *Ptr) {
QualType T;
- T.Value.setFromOpaqueValue(Ptr);
+ T.Value.setFromOpaqueValue(const_cast<void*>(Ptr));
return T;
}
- Type &operator*() const {
+ const Type &operator*() const {
return *getTypePtr();
}
- Type *operator->() const {
+ const Type *operator->() const {
return getTypePtr();
}
@@ -510,7 +465,7 @@ public:
/// "volatile" qualifier set, without looking through typedefs that may have
/// added "volatile" at a different level.
bool isLocalVolatileQualified() const {
- return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
+ return (getLocalFastQualifiers() & Qualifiers::Volatile);
}
/// \brief Determine whether this type is volatile-qualified.
@@ -536,13 +491,7 @@ public:
/// \brief Retrieve the set of qualifiers local to this particular QualType
/// instance, not including any qualifiers acquired through typedefs or
/// other sugar.
- Qualifiers getLocalQualifiers() const {
- Qualifiers Quals;
- if (hasLocalNonFastQualifiers())
- Quals = getExtQualsUnsafe()->getQualifiers();
- Quals.addFastQualifiers(getLocalFastQualifiers());
- return Quals;
- }
+ Qualifiers getLocalQualifiers() const;
/// \brief Retrieve the set of qualifiers applied to this type.
Qualifiers getQualifiers() const;
@@ -551,21 +500,13 @@ public:
/// local to this particular QualType instance, not including any qualifiers
/// acquired through typedefs or other sugar.
unsigned getLocalCVRQualifiers() const {
- unsigned CVR = getLocalFastQualifiers();
- if (isLocalVolatileQualified())
- CVR |= Qualifiers::Volatile;
- return CVR;
+ return getLocalFastQualifiers();
}
/// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// applied to this type.
unsigned getCVRQualifiers() const;
- /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
- /// applied to this type, looking through any number of unqualified array
- /// types to their element types' qualifiers.
- unsigned getCVRQualifiersThroughArrayTypes() const;
-
bool isConstant(ASTContext& Ctx) const {
return QualType::isConstant(*this, Ctx);
}
@@ -587,16 +528,13 @@ public:
Value.setInt(Value.getInt() | TQs);
}
- // FIXME: The remove* functions are semantically broken, because they might
- // not remove a qualifier stored on a typedef. Most of the with* functions
- // have the same problem.
- void removeConst();
- void removeVolatile();
- void removeRestrict();
- void removeCVRQualifiers(unsigned Mask);
+ void removeLocalConst();
+ void removeLocalVolatile();
+ void removeLocalRestrict();
+ void removeLocalCVRQualifiers(unsigned Mask);
- void removeFastQualifiers() { Value.setInt(0); }
- void removeFastQualifiers(unsigned Mask) {
+ void removeLocalFastQualifiers() { Value.setInt(0); }
+ void removeLocalFastQualifiers(unsigned Mask) {
assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
Value.setInt(Value.getInt() & ~Mask);
}
@@ -611,31 +549,54 @@ public:
// Creates a type with exactly the given fast qualifiers, removing
// any existing fast qualifiers.
- QualType withExactFastQualifiers(unsigned TQs) const {
- return withoutFastQualifiers().withFastQualifiers(TQs);
+ QualType withExactLocalFastQualifiers(unsigned TQs) const {
+ return withoutLocalFastQualifiers().withFastQualifiers(TQs);
}
// Removes fast qualifiers, but leaves any extended qualifiers in place.
- QualType withoutFastQualifiers() const {
+ QualType withoutLocalFastQualifiers() const {
QualType T = *this;
- T.removeFastQualifiers();
+ T.removeLocalFastQualifiers();
return T;
}
+ QualType getCanonicalType() const;
+
/// \brief Return this type with all of the instance-specific qualifiers
/// removed, but without removing any qualifiers that may have been applied
/// through typedefs.
QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); }
- /// \brief Return the unqualified form of the given type, which might be
- /// desugared to eliminate qualifiers introduced via typedefs.
- QualType getUnqualifiedType() const {
- QualType T = getLocalUnqualifiedType();
- if (!T.hasQualifiers())
- return T;
-
- return getUnqualifiedTypeSlow();
- }
+ /// \brief Retrieve the unqualified variant of the given type,
+ /// removing as little sugar as possible.
+ ///
+ /// This routine looks through various kinds of sugar to find the
+ /// least-desugared type that is unqualified. For example, given:
+ ///
+ /// \code
+ /// typedef int Integer;
+ /// typedef const Integer CInteger;
+ /// typedef CInteger DifferenceType;
+ /// \endcode
+ ///
+ /// Executing \c getUnqualifiedType() on the type \c DifferenceType will
+ /// desugar until we hit the type \c Integer, which has no qualifiers on it.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline QualType getUnqualifiedType() const;
+
+ /// getSplitUnqualifiedType - Retrieve the unqualified variant of the
+ /// given type, removing as little sugar as possible.
+ ///
+ /// Like getUnqualifiedType(), but also returns the set of
+ /// qualifiers that were built up.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline SplitQualType getSplitUnqualifiedType() const;
bool isMoreQualifiedThan(QualType Other) const;
bool isAtLeastAsQualifiedAs(QualType Other) const;
@@ -659,8 +620,20 @@ public:
/// concrete.
///
/// Qualifiers are left in place.
- QualType getDesugaredType() const {
- return QualType::getDesugaredType(*this);
+ QualType getDesugaredType(const ASTContext &Context) const {
+ return getDesugaredType(*this, Context);
+ }
+
+ SplitQualType getSplitDesugaredType() const {
+ return getSplitDesugaredType(*this);
+ }
+
+ /// IgnoreParens - Returns the specified type after dropping any
+ /// outer-level parentheses.
+ QualType IgnoreParens() const {
+ if (isa<ParenType>(*this))
+ return QualType::IgnoreParens(*this);
+ return *this;
}
/// operator==/!= - Indicate whether the specified types and qualifiers are
@@ -671,7 +644,13 @@ public:
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
return LHS.Value != RHS.Value;
}
- std::string getAsString() const;
+ std::string getAsString() const {
+ return getAsString(split());
+ }
+ static std::string getAsString(SplitQualType split) {
+ return getAsString(split.first, split.second);
+ }
+ static std::string getAsString(const Type *ty, Qualifiers qs);
std::string getAsString(const PrintingPolicy &Policy) const {
std::string S;
@@ -679,7 +658,16 @@ public:
return S;
}
void getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const;
+ const PrintingPolicy &Policy) const {
+ return getAsStringInternal(split(), Str, Policy);
+ }
+ static void getAsStringInternal(SplitQualType split, std::string &out,
+ const PrintingPolicy &policy) {
+ return getAsStringInternal(split.first, split.second, out, policy);
+ }
+ static void getAsStringInternal(const Type *ty, Qualifiers qs,
+ std::string &out,
+ const PrintingPolicy &policy);
void dump(const char *s) const;
void dump() const;
@@ -704,12 +692,29 @@ public:
return getObjCGCAttr() == Qualifiers::Strong;
}
+ enum DestructionKind {
+ DK_none,
+ DK_cxx_destructor
+ };
+
+ /// isDestructedType - nonzero if objects of this type require
+ /// non-trivial work to clean up after. Non-zero because it's
+ /// conceivable that qualifiers (objc_gc(weak)?) could make
+ /// something require destruction.
+ DestructionKind isDestructedType() const {
+ return isDestructedTypeImpl(*this);
+ }
+
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);
+ static QualType getDesugaredType(QualType T, const ASTContext &Context);
+ static SplitQualType getSplitDesugaredType(QualType T);
+ static SplitQualType getSplitUnqualifiedTypeImpl(QualType type);
+ static QualType IgnoreParens(QualType T);
+ static DestructionKind isDestructedTypeImpl(QualType type);
};
} // end clang.
@@ -718,7 +723,7 @@ namespace llvm {
/// Implement simplify_type for QualType, so that we can dyn_cast from QualType
/// to a specific Type class.
template<> struct simplify_type<const ::clang::QualType> {
- typedef ::clang::Type* SimpleType;
+ typedef const ::clang::Type *SimpleType;
static SimpleType getSimplifiedValue(const ::clang::QualType &Val) {
return Val.getTypePtr();
}
@@ -744,6 +749,106 @@ public:
namespace clang {
+/// \brief Base class that is common to both the \c ExtQuals and \c Type
+/// classes, which allows \c QualType to access the common fields between the
+/// two.
+///
+class ExtQualsTypeCommonBase {
+ ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
+ : BaseType(baseType), CanonicalType(canon) {}
+
+ /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
+ /// a self-referential pointer (for \c Type).
+ ///
+ /// This pointer allows an efficient mapping from a QualType to its
+ /// underlying type pointer.
+ const Type *const BaseType;
+
+ /// \brief The canonical type of this type. A QualType.
+ QualType CanonicalType;
+
+ friend class QualType;
+ friend class Type;
+ friend class ExtQuals;
+};
+
+/// ExtQuals - We can encode up to four 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', 'restrict', and 'volatile' qualifiers
+/// in three low bits on the QualType pointer; a fourth bit records whether
+/// the pointer is an ExtQuals node. The extended qualifiers (address spaces,
+/// Objective-C GC attributes) are much more rare.
+class ExtQuals : public ExtQualsTypeCommonBase, 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.
+
+ /// Quals - the immutable set of qualifiers applied by this
+ /// node; always contains extended qualifiers.
+ Qualifiers Quals;
+
+ ExtQuals *this_() { return this; }
+
+public:
+ ExtQuals(const Type *baseType, QualType canon, Qualifiers quals)
+ : ExtQualsTypeCommonBase(baseType,
+ canon.isNull() ? QualType(this_(), 0) : canon),
+ 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 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; }
+
+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);
+ }
+};
+
+/// \brief The kind of C++0x ref-qualifier associated with a function type,
+/// which determines whether a member function's "this" object can be an
+/// lvalue, rvalue, or neither.
+enum RefQualifierKind {
+ /// \brief No ref-qualifier was provided.
+ RQ_None = 0,
+ /// \brief An lvalue ref-qualifier was provided (\c &).
+ RQ_LValue,
+ /// \brief An rvalue ref-qualifier was provided (\c &&).
+ RQ_RValue
+};
+
/// Type - This is the base class of the type hierarchy. A central concept
/// with types is that each type always has a canonical type. A canonical type
/// is the type with any typedef names stripped out of it or the types it
@@ -769,7 +874,7 @@ namespace clang {
///
/// Types, once created, are immutable.
///
-class Type {
+class Type : public ExtQualsTypeCommonBase {
public:
enum TypeClass {
#define TYPE(Class, Base) Class,
@@ -783,53 +888,249 @@ private:
Type(const Type&); // DO NOT IMPLEMENT.
void operator=(const Type&); // DO NOT IMPLEMENT.
- QualType CanonicalType;
+ /// Bitfields required by the Type class.
+ class TypeBitfields {
+ friend class Type;
+ template <class T> friend class TypePropertyCache;
- /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
- unsigned TC : 8;
+ /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
+ unsigned TC : 8;
- /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
- /// Note that this should stay at the end of the ivars for Type so that
- /// subclasses can pack their bitfields into the same word.
- bool Dependent : 1;
+ /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ /// 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 Dependent : 1;
- /// \brief Whether the linkage of this type is already known.
- mutable bool LinkageKnown : 1;
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ unsigned VariablyModified : 1;
+
+ /// \brief Whether this type contains an unexpanded parameter pack
+ /// (for C++0x variadic templates).
+ unsigned ContainsUnexpandedParameterPack : 1;
+
+ /// \brief Nonzero if the cache (i.e. the bitfields here starting
+ /// with 'Cache') is valid. If so, then this is a
+ /// LangOptions::VisibilityMode+1.
+ mutable unsigned CacheValidAndVisibility : 2;
+
+ /// \brief Linkage of this type.
+ mutable unsigned CachedLinkage : 2;
+
+ /// \brief Whether this type involves and local or unnamed types.
+ mutable unsigned CachedLocalOrUnnamed : 1;
- /// \brief Linkage of this type.
- mutable unsigned CachedLinkage : 2;
+ /// \brief FromAST - Whether this type comes from an AST file.
+ mutable unsigned FromAST : 1;
+
+ bool isCacheValid() const {
+ return (CacheValidAndVisibility != 0);
+ }
+ Visibility getVisibility() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Visibility>(CacheValidAndVisibility-1);
+ }
+ Linkage getLinkage() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Linkage>(CachedLinkage);
+ }
+ bool hasLocalOrUnnamedType() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return CachedLocalOrUnnamed;
+ }
+ };
+ enum { NumTypeBits = 17 };
+
+protected:
+ // These classes allow subclasses to somewhat cleanly pack bitfields
+ // into Type.
+
+ class ArrayTypeBitfields {
+ friend class ArrayType;
+
+ unsigned : NumTypeBits;
+
+ /// IndexTypeQuals - CVR qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ unsigned IndexTypeQuals : 3;
+
+ /// SizeModifier - storage class qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ /// Actually an ArrayType::ArraySizeModifier.
+ unsigned SizeModifier : 3;
+ };
+
+ class BuiltinTypeBitfields {
+ friend class BuiltinType;
+
+ unsigned : NumTypeBits;
+
+ /// The kind (BuiltinType::Kind) of builtin type this is.
+ unsigned Kind : 8;
+ };
+
+ class FunctionTypeBitfields {
+ friend class FunctionType;
+
+ unsigned : NumTypeBits;
+
+ /// Extra information which affects how the function is called, like
+ /// regparm and the calling convention.
+ unsigned ExtInfo : 8;
+
+ /// Whether the function is variadic. Only used by FunctionProtoType.
+ unsigned Variadic : 1;
+
+ /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// other bitfields.
+ /// The qualifiers are part of FunctionProtoType because...
+ ///
+ /// C++ 8.3.5p4: The return type, the parameter type list and the
+ /// cv-qualifier-seq, [...], are part of the function type.
+ unsigned TypeQuals : 3;
+
+ /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+ ///
+ /// This is a value of type \c RefQualifierKind.
+ unsigned RefQualifier : 2;
+ };
+
+ class ObjCObjectTypeBitfields {
+ friend class ObjCObjectType;
+
+ unsigned : NumTypeBits;
+
+ /// NumProtocols - The number of protocols stored directly on this
+ /// object type.
+ unsigned NumProtocols : 32 - NumTypeBits;
+ };
+
+ class ReferenceTypeBitfields {
+ friend class ReferenceType;
+
+ unsigned : NumTypeBits;
+
+ /// True if the type was originally spelled with an lvalue sigil.
+ /// This is never true of rvalue references but can also be false
+ /// on lvalue references because of C++0x [dcl.typedef]p9,
+ /// as follows:
+ ///
+ /// typedef int &ref; // lvalue, spelled lvalue
+ /// typedef int &&rvref; // rvalue
+ /// ref &a; // lvalue, inner ref, spelled lvalue
+ /// ref &&a; // lvalue, inner ref
+ /// rvref &a; // lvalue, inner ref, spelled lvalue
+ /// rvref &&a; // rvalue, inner ref
+ unsigned SpelledAsLValue : 1;
+
+ /// True if the inner type is a reference type. This only happens
+ /// in non-canonical forms.
+ unsigned InnerRef : 1;
+ };
+
+ class TypeWithKeywordBitfields {
+ friend class TypeWithKeyword;
+
+ unsigned : NumTypeBits;
+
+ /// An ElaboratedTypeKeyword. 8 bits for efficient access.
+ unsigned Keyword : 8;
+ };
+
+ class VectorTypeBitfields {
+ friend class VectorType;
+
+ unsigned : NumTypeBits;
+
+ /// VecKind - The kind of vector, either a generic vector type or some
+ /// target-specific vector type such as for AltiVec or Neon.
+ unsigned VecKind : 3;
+
+ /// NumElements - The number of elements in the vector.
+ unsigned NumElements : 29 - NumTypeBits;
+ };
+
+ class AttributedTypeBitfields {
+ friend class AttributedType;
- /// \brief FromAST - Whether this type comes from an AST file.
- mutable bool FromAST : 1;
+ unsigned : NumTypeBits;
+ /// AttrKind - an AttributedType::Kind
+ unsigned AttrKind : 32 - NumTypeBits;
+ };
+
+ union {
+ TypeBitfields TypeBits;
+ ArrayTypeBitfields ArrayTypeBits;
+ AttributedTypeBitfields AttributedTypeBits;
+ BuiltinTypeBitfields BuiltinTypeBits;
+ FunctionTypeBitfields FunctionTypeBits;
+ ObjCObjectTypeBitfields ObjCObjectTypeBits;
+ ReferenceTypeBitfields ReferenceTypeBits;
+ TypeWithKeywordBitfields TypeWithKeywordBits;
+ VectorTypeBitfields VectorTypeBits;
+ };
+
+private:
/// \brief Set whether this type comes from an AST file.
void setFromAST(bool V = true) const {
- FromAST = V;
+ TypeBits.FromAST = V;
}
-protected:
- /// \brief Compute the linkage of this type.
- virtual Linkage getLinkageImpl() const;
-
- enum { BitsRemainingInType = 19 };
+ template <class T> friend class TypePropertyCache;
+protected:
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
- Type(TypeClass tc, QualType Canonical, bool dependent)
- : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
- TC(tc), Dependent(dependent), LinkageKnown(false),
- CachedLinkage(NoLinkage), FromAST(false) {}
- virtual ~Type();
+ Type(TypeClass tc, QualType canon, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : ExtQualsTypeCommonBase(this,
+ canon.isNull() ? QualType(this_(), 0) : canon) {
+ TypeBits.TC = tc;
+ TypeBits.Dependent = Dependent;
+ TypeBits.VariablyModified = VariablyModified;
+ TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ TypeBits.CacheValidAndVisibility = 0;
+ TypeBits.CachedLocalOrUnnamed = false;
+ TypeBits.CachedLinkage = NoLinkage;
+ TypeBits.FromAST = false;
+ }
friend class ASTContext;
+ void setDependent(bool D = true) { TypeBits.Dependent = D; }
+ void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; }
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ TypeBits.ContainsUnexpandedParameterPack = PP;
+ }
+
public:
- TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
+ TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
/// \brief Whether this type comes from an AST file.
- bool isFromAST() const { return FromAST; }
+ bool isFromAST() const { return TypeBits.FromAST; }
+
+ /// \brief Whether this type is or contains an unexpanded parameter
+ /// pack, used to support C++0x variadic templates.
+ ///
+ /// A type that contains a parameter pack shall be expanded by the
+ /// ellipsis operator at some point. For example, the typedef in the
+ /// following example contains an unexpanded parameter pack 'T':
+ ///
+ /// \code
+ /// template<typename ...T>
+ /// struct X {
+ /// typedef T* pointer_types; // ill-formed; T is a parameter pack.
+ /// };
+ /// \endcode
+ ///
+ /// Note that this routine does not specify which
+ bool containsUnexpandedParameterPack() const {
+ return TypeBits.ContainsUnexpandedParameterPack;
+ }
+ /// Determines if this type would be canonical if it had no further
+ /// qualification.
bool isCanonicalUnqualified() const {
- return CanonicalType.getTypePtr() == this;
+ return CanonicalType == QualType(this, 0);
}
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
@@ -846,6 +1147,14 @@ public:
bool isIncompleteOrObjectType() const {
return !isFunctionType();
}
+
+ /// \brief Determine whether this type is an object type.
+ bool isObjectType() const {
+ // C++ [basic.types]p8:
+ // An object type is a (possibly cv-qualified) type that is not a
+ // function type, not a reference type, and not a void type.
+ return !isReferenceType() && !isFunctionType() && !isVoidType();
+ }
/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
bool isPODType() const;
@@ -854,10 +1163,6 @@ public:
/// (C++0x [basic.types]p10)
bool isLiteralType() const;
- /// 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.
@@ -867,6 +1172,12 @@ public:
/// isSpecificBuiltinType - Test for a particular builtin type.
bool isSpecificBuiltinType(unsigned K) const;
+ /// isPlaceholderType - Test for a type which does not represent an
+ /// actual type-system type but is instead used as a placeholder for
+ /// various convenient purposes within Clang. All such types are
+ /// BuiltinTypes.
+ bool isPlaceholderType() 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)
@@ -879,6 +1190,9 @@ public:
/// \brief Determine whether this type is an integral or enumeration type.
bool isIntegralOrEnumerationType() const;
+ /// \brief Determine whether this type is an integral or unscoped enumeration
+ /// type.
+ bool isIntegralOrUnscopedEnumerationType() const;
/// Floating point categories.
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
@@ -938,10 +1252,33 @@ public:
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
+ enum ScalarTypeKind {
+ STK_Pointer,
+ STK_MemberPointer,
+ STK_Bool,
+ STK_Integral,
+ STK_Floating,
+ STK_IntegralComplex,
+ STK_FloatingComplex
+ };
+ /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ ScalarTypeKind getScalarTypeKind() const;
+
/// isDependentType - Whether this type is a dependent type, meaning
/// that its definition somehow depends on a template parameter
/// (C++ [temp.dep.type]).
- bool isDependentType() const { return Dependent; }
+ bool isDependentType() const { return TypeBits.Dependent; }
+
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ bool isVariablyModifiedType() const { return TypeBits.VariablyModified; }
+
+ /// \brief Whether this type involves a variable-length array type
+ /// with a definite size.
+ bool hasSizedVLAType() const;
+
+ /// \brief Whether this type is or contains a local or unnamed type.
+ bool hasUnnamedOrLocalType() const;
+
bool isOverloadableType() const;
/// \brief Determine wither this type is a C++ elaborated-type-specifier.
@@ -991,15 +1328,41 @@ public:
/// because the type is a RecordType or because it is the injected-class-name
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
+
+ /// \brief Get the AutoType whose type will be deduced for a variable with
+ /// an initializer of this type. This looks through declarators like pointer
+ /// types, but not through decltype or typedefs.
+ AutoType *getContainedAutoType() const;
- // Member-template getAs<specific type>'. Look through sugar for
- // an instance of <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.
+ /// Member-template getAs<specific type>'. Look through sugar for
+ /// an instance of <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;
+ /// A variant of getAs<> for array types which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *getAsArrayTypeUnsafe() const;
+
+ /// Member-template castAs<specific type>. Look through sugar for
+ /// the underlying instance of <specific type>.
+ ///
+ /// This method has the same relationship to getAs<T> as cast<T> has
+ /// to dyn_cast<T>; which is to say, the underlying type *must*
+ /// have the intended type, and this method will never return null.
+ template <typename T> const T *castAs() const;
+
+ /// A variant of castAs<> for array type which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *castAsArrayTypeUnsafe() const;
+
+ /// getBaseElementTypeUnsafe - Get the base element type of this
+ /// type, potentially discarding type qualifiers. This method
+ /// should never be used when type qualifiers are meaningful.
+ const Type *getBaseElementTypeUnsafe() const;
+
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -1040,6 +1403,12 @@ public:
/// \brief Determine the linkage of this type.
Linkage getLinkage() const;
+
+ /// \brief Determine the visibility of this type.
+ Visibility getVisibility() const;
+
+ /// \brief Determine the linkage and visibility of this type.
+ std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
/// \brief Note that the linkage is no longer known.
void ClearLinkageCache();
@@ -1067,6 +1436,9 @@ template <> inline const TypedefType *Type::getAs() const {
#define LEAF_TYPE(Class) \
template <> inline const Class##Type *Type::getAs() const { \
return dyn_cast<Class##Type>(CanonicalType); \
+} \
+template <> inline const Class##Type *Type::castAs() const { \
+ return cast<Class##Type>(CanonicalType); \
}
#include "clang/AST/TypeNodes.def"
@@ -1081,6 +1453,7 @@ public:
Bool, // This is bool and/or _Bool.
Char_U, // This is 'char' for targets where char is unsigned.
UChar, // This is explicitly qualified unsigned char.
+ WChar_U, // This is 'wchar_t' for C++, when unsigned.
Char16, // This is 'char16_t' for C++.
Char32, // This is 'char32_t' for C++.
UShort,
@@ -1091,7 +1464,7 @@ public:
Char_S, // This is 'char' for targets where char is signed.
SChar, // This is explicitly qualified signed char.
- WChar, // This is 'wchar_t' for C++.
+ WChar_S, // This is 'wchar_t' for C++, when signed.
Short,
Int,
Long,
@@ -1102,11 +1475,13 @@ public:
NullPtr, // This is the type of C++0x 'nullptr'.
- Overload, // This represents the type of an overloaded function declaration.
- Dependent, // This represents the type of a type-dependent expression.
+ /// This represents the type of an expression whose type is
+ /// totally unknown, e.g. 'T::foo'. It is permitted for this to
+ /// appear in situations where the structure of the type is
+ /// theoretically deducible.
+ Dependent,
- UndeducedAuto, // In C++0x, this represents the type of an auto variable
- // that has not been deduced yet.
+ Overload, // This represents the type of an overloaded function declaration.
/// The primitive Objective C 'id' type. The type pointed to by the
/// user-visible 'id' type. Only ever shows up in an AST as the base
@@ -1120,37 +1495,42 @@ public:
ObjCSel // This represents the ObjC 'SEL' type.
};
-private:
- Kind TypeKind;
-
-protected:
- virtual Linkage getLinkageImpl() const;
-
+
public:
BuiltinType(Kind K)
- : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)),
- TypeKind(K) {}
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*VariablyModified=*/false,
+ /*Unexpanded paramter pack=*/false) {
+ BuiltinTypeBits.Kind = K;
+ }
- Kind getKind() const { return TypeKind; }
+ Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
const char *getName(const LangOptions &LO) const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
bool isInteger() const {
- return TypeKind >= Bool && TypeKind <= Int128;
+ return getKind() >= Bool && getKind() <= Int128;
}
bool isSignedInteger() const {
- return TypeKind >= Char_S && TypeKind <= Int128;
+ return getKind() >= Char_S && getKind() <= Int128;
}
bool isUnsignedInteger() const {
- return TypeKind >= Bool && TypeKind <= UInt128;
+ return getKind() >= Bool && getKind() <= UInt128;
}
bool isFloatingPoint() const {
- return TypeKind >= Float && TypeKind <= LongDouble;
+ return getKind() >= Float && getKind() <= LongDouble;
+ }
+
+ /// Determines whether this type is a "forbidden" placeholder type,
+ /// i.e. a type which cannot appear in arbitrary positions in a
+ /// fully-formed expression.
+ bool isPlaceholderType() const {
+ return getKind() == Overload;
}
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
@@ -1163,14 +1543,13 @@ public:
class ComplexType : public Type, public llvm::FoldingSetNode {
QualType ElementType;
ComplexType(QualType Element, QualType CanonicalPtr) :
- Type(Complex, CanonicalPtr, Element->isDependentType()),
+ Type(Complex, CanonicalPtr, Element->isDependentType(),
+ Element->isVariablyModifiedType(),
+ Element->containsUnexpandedParameterPack()),
ElementType(Element) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
@@ -1188,19 +1567,50 @@ public:
static bool classof(const ComplexType *) { return true; }
};
+/// ParenType - Sugar for parentheses used when specifying types.
+///
+class ParenType : public Type, public llvm::FoldingSetNode {
+ QualType Inner;
+
+ ParenType(QualType InnerType, QualType CanonType) :
+ Type(Paren, CanonType, InnerType->isDependentType(),
+ InnerType->isVariablyModifiedType(),
+ InnerType->containsUnexpandedParameterPack()),
+ Inner(InnerType) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getInnerType() const { return Inner; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getInnerType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getInnerType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) {
+ Inner.Profile(ID);
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Paren; }
+ static bool classof(const ParenType *) { return true; }
+};
+
/// PointerType - C99 6.7.5.1 - Pointer Declarators.
///
class PointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
PointerType(QualType Pointee, QualType CanonicalPtr) :
- Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) {
+ Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getPointeeType() const { return PointeeType; }
@@ -1226,14 +1636,13 @@ public:
class BlockPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType; // Block is some kind of pointer type
BlockPointerType(QualType Pointee, QualType CanonicalCls) :
- Type(BlockPointer, CanonicalCls, Pointee->isDependentType()),
+ Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
// Get the pointee type. Pointee is required to always be a function type.
@@ -1260,48 +1669,33 @@ public:
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
- /// True if the type was originally spelled with an lvalue sigil.
- /// This is never true of rvalue references but can also be false
- /// on lvalue references because of C++0x [dcl.typedef]p9,
- /// as follows:
- ///
- /// typedef int &ref; // lvalue, spelled lvalue
- /// typedef int &&rvref; // rvalue
- /// ref &a; // lvalue, inner ref, spelled lvalue
- /// ref &&a; // lvalue, inner ref
- /// rvref &a; // lvalue, inner ref, spelled lvalue
- /// rvref &&a; // rvalue, inner ref
- bool SpelledAsLValue;
-
- /// True if the inner type is a reference type. This only happens
- /// in non-canonical forms.
- bool InnerRef;
-
protected:
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
bool SpelledAsLValue) :
- Type(tc, CanonicalRef, Referencee->isDependentType()),
- PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
- InnerRef(Referencee->isReferenceType()) {
+ Type(tc, CanonicalRef, Referencee->isDependentType(),
+ Referencee->isVariablyModifiedType(),
+ Referencee->containsUnexpandedParameterPack()),
+ PointeeType(Referencee)
+ {
+ ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue;
+ ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
}
- virtual Linkage getLinkageImpl() const;
-
public:
- bool isSpelledAsLValue() const { return SpelledAsLValue; }
- bool isInnerRef() const { return InnerRef; }
+ bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
+ bool isInnerRef() const { return ReferenceTypeBits.InnerRef; }
QualType getPointeeTypeAsWritten() const { return PointeeType; }
QualType getPointeeType() const {
// FIXME: this might strip inner qualifiers; okay?
const ReferenceType *T = this;
- while (T->InnerRef)
- T = T->PointeeType->getAs<ReferenceType>();
+ while (T->isInnerRef())
+ T = T->PointeeType->castAs<ReferenceType>();
return T->PointeeType;
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, PointeeType, SpelledAsLValue);
+ Profile(ID, PointeeType, isSpelledAsLValue());
}
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Referencee,
@@ -1362,14 +1756,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
Type(MemberPointer, CanonicalPtr,
- Cls->isDependentType() || Pointee->isDependentType()),
+ Cls->isDependentType() || Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ (Cls->containsUnexpandedParameterPack() ||
+ Pointee->containsUnexpandedParameterPack())),
PointeeType(Pointee), Class(Cls) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getPointeeType() const { return PointeeType; }
@@ -1420,14 +1814,6 @@ private:
/// ElementType - The element type of the array.
QualType ElementType;
- // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum
- /// NOTE: These fields are packed into the bitfields space in the Type class.
- unsigned SizeModifier : 2;
-
- /// IndexTypeQuals - Capture qualifiers in declarations like:
- /// 'int X[static restrict 4]'. For function parameters only.
- unsigned IndexTypeQuals : 3;
-
protected:
// C++ [temp.dep.type]p1:
// A type is dependent if it is...
@@ -1435,23 +1821,29 @@ protected:
// size is specified by a constant expression that is
// value-dependent,
ArrayType(TypeClass tc, QualType et, QualType can,
- ArraySizeModifier sm, unsigned tq)
- : Type(tc, can, et->isDependentType() || tc == DependentSizedArray),
- ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {}
+ ArraySizeModifier sm, unsigned tq,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType()),
+ ContainsUnexpandedParameterPack),
+ ElementType(et) {
+ ArrayTypeBits.IndexTypeQuals = tq;
+ ArrayTypeBits.SizeModifier = sm;
+ }
friend class ASTContext; // ASTContext creates these.
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
ArraySizeModifier getSizeModifier() const {
- return ArraySizeModifier(SizeModifier);
+ return ArraySizeModifier(ArrayTypeBits.SizeModifier);
}
Qualifiers getIndexTypeQualifiers() const {
- return Qualifiers::fromCVRMask(IndexTypeQuals);
+ return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers());
+ }
+ unsigned getIndexTypeCVRQualifiers() const {
+ return ArrayTypeBits.IndexTypeQuals;
}
- unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray ||
@@ -1471,12 +1863,14 @@ class ConstantArrayType : public ArrayType {
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(ConstantArray, et, can, sm, tq),
+ : ArrayType(ConstantArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
Size(size) {}
protected:
ConstantArrayType(TypeClass tc, QualType et, QualType can,
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
- : ArrayType(tc, et, can, sm, tq), Size(size) {}
+ : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
+ Size(size) {}
friend class ASTContext; // ASTContext creates these.
public:
const llvm::APInt &getSize() const { return Size; }
@@ -1519,7 +1913,8 @@ class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(IncompleteArray, et, can, sm, tq) {}
+ : ArrayType(IncompleteArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()) {}
friend class ASTContext; // ASTContext creates these.
public:
bool isSugared() const { return false; }
@@ -1570,7 +1965,8 @@ class VariableArrayType : public ArrayType {
VariableArrayType(QualType et, QualType can, Expr *e,
ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
- : ArrayType(VariableArray, et, can, sm, tq),
+ : ArrayType(VariableArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
@@ -1613,7 +2009,7 @@ public:
/// until template instantiation occurs, at which point this will
/// become either a ConstantArrayType or a VariableArrayType.
class DependentSizedArrayType : public ArrayType {
- ASTContext &Context;
+ const ASTContext &Context;
/// \brief An assignment expression that will instantiate to the
/// size of the array.
@@ -1625,11 +2021,10 @@ class DependentSizedArrayType : public ArrayType {
/// Brackets - The left and right array brackets.
SourceRange Brackets;
- DependentSizedArrayType(ASTContext &Context, QualType et, QualType can,
+ DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can,
Expr *e, ArraySizeModifier sm, unsigned tq,
- SourceRange brackets)
- : ArrayType(DependentSizedArray, et, can, sm, tq),
- Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
+ SourceRange brackets);
+
friend class ASTContext; // ASTContext creates these.
public:
@@ -1658,7 +2053,7 @@ public:
getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType ET, ArraySizeModifier SizeMod,
unsigned TypeQuals, Expr *E);
};
@@ -1672,17 +2067,15 @@ public:
/// }
/// @endcode
class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
Expr *SizeExpr;
/// ElementType - The element type of the array.
QualType ElementType;
SourceLocation loc;
- DependentSizedExtVectorType(ASTContext &Context, QualType ElementType,
- QualType can, Expr *SizeExpr, SourceLocation loc)
- : Type (DependentSizedExtVector, can, true),
- Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
- loc(loc) {}
+ DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType,
+ QualType can, Expr *SizeExpr, SourceLocation loc);
+
friend class ASTContext;
public:
@@ -1702,7 +2095,7 @@ public:
Profile(ID, Context, getElementType(), getSizeExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType ElementType, Expr *SizeExpr);
};
@@ -1714,53 +2107,49 @@ public:
/// client is responsible for converting the size into the number of elements.
class VectorType : public Type, public llvm::FoldingSetNode {
public:
- enum AltiVecSpecific {
- NotAltiVec, // is not AltiVec vector
- AltiVec, // is AltiVec vector
- Pixel, // is AltiVec 'vector Pixel'
- Bool // is AltiVec 'vector bool ...'
+ enum VectorKind {
+ GenericVector, // not a target-specific vector type
+ AltiVecVector, // is AltiVec vector
+ AltiVecPixel, // is AltiVec 'vector Pixel'
+ AltiVecBool, // is AltiVec 'vector bool ...'
+ NeonVector, // is ARM Neon vector
+ NeonPolyVector // is ARM Neon polynomial vector
};
protected:
/// ElementType - The element type of the vector.
QualType ElementType;
- /// NumElements - The number of elements in the vector.
- unsigned NumElements;
-
- AltiVecSpecific AltiVecSpec;
-
VectorType(QualType vecType, unsigned nElements, QualType canonType,
- AltiVecSpecific altiVecSpec) :
- Type(Vector, canonType, vecType->isDependentType()),
- ElementType(vecType), NumElements(nElements), AltiVecSpec(altiVecSpec) {}
+ VectorKind vecKind);
+
VectorType(TypeClass tc, QualType vecType, unsigned nElements,
- QualType canonType, AltiVecSpecific altiVecSpec)
- : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
- NumElements(nElements), AltiVecSpec(altiVecSpec) {}
+ QualType canonType, VectorKind vecKind);
+
friend class ASTContext; // ASTContext creates these.
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
- unsigned getNumElements() const { return NumElements; }
+ unsigned getNumElements() const { return VectorTypeBits.NumElements; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- AltiVecSpecific getAltiVecSpecific() const { return AltiVecSpec; }
+ VectorKind getVectorKind() const {
+ return VectorKind(VectorTypeBits.VecKind);
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getElementType(), getNumElements(), getTypeClass(), AltiVecSpec);
+ Profile(ID, getElementType(), getNumElements(),
+ getTypeClass(), getVectorKind());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
unsigned NumElements, TypeClass TypeClass,
- unsigned AltiVecSpec) {
+ VectorKind VecKind) {
ID.AddPointer(ElementType.getAsOpaquePtr());
ID.AddInteger(NumElements);
ID.AddInteger(TypeClass);
- ID.AddInteger(AltiVecSpec);
+ ID.AddInteger(VecKind);
}
static bool classof(const Type *T) {
@@ -1776,7 +2165,7 @@ public:
/// points, colors, and textures (modeled after OpenGL Shading Language).
class ExtVectorType : public VectorType {
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
- VectorType(ExtVector, vecType, nElements, canonType, NotAltiVec) {}
+ VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
friend class ASTContext; // ASTContext creates these.
public:
static int getPointAccessorIdx(char c) {
@@ -1823,7 +2212,7 @@ public:
bool isAccessorWithinNumElements(char c) const {
if (int idx = getAccessorIdx(c)+1)
- return unsigned(idx-1) < NumElements;
+ return unsigned(idx-1) < getNumElements();
return false;
}
bool isSugared() const { return false; }
@@ -1839,40 +2228,20 @@ public:
/// class of FunctionNoProtoType and FunctionProtoType.
///
class FunctionType : public Type {
- virtual void ANCHOR(); // Key function for FunctionType.
-
- /// SubClassData - This field is owned by the subclass, put here to pack
- /// tightly with the ivars in Type.
- bool SubClassData : 1;
-
- /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
- /// other bitfields.
- /// The qualifiers are part of FunctionProtoType because...
- ///
- /// C++ 8.3.5p4: The return type, the parameter type list and the
- /// cv-qualifier-seq, [...], are part of the function type.
- ///
- unsigned TypeQuals : 3;
-
- /// NoReturn - Indicates if the function type is attribute noreturn.
- unsigned NoReturn : 1;
-
- /// RegParm - How many arguments to pass inreg.
- unsigned RegParm : 3;
-
- /// CallConv - The calling convention used by the function.
- unsigned CallConv : 3;
-
// The type returned by the function.
QualType ResultType;
public:
- // This class is used for passing arround the information needed to
- // construct a call. It is not actually used for storage, just for
- // factoring together common arguments.
- // If you add a field (say Foo), other than the obvious places (both, constructors,
- // compile failures), what you need to update is
- // * Operetor==
+ /// ExtInfo - A class which abstracts out some details necessary for
+ /// making a call.
+ ///
+ /// It is not actually used directly for storing this information in
+ /// a FunctionType, although FunctionType does currently use the
+ /// same bit-pattern.
+ ///
+ // If you add a field (say Foo), other than the obvious places (both,
+ // constructors, compile failures), what you need to update is
+ // * Operator==
// * getFoo
// * withFoo
// * functionType. Add Foo, getFoo.
@@ -1883,76 +2252,100 @@ class FunctionType : public Type {
// * TypePrinter::PrintFunctionProto
// * AST read and write
// * Codegen
-
class ExtInfo {
+ // Feel free to rearrange or add bits, but if you go over 8,
+ // you'll need to adjust both the Bits field below and
+ // Type::FunctionTypeBitfields.
+
+ // | CC |noreturn|regparm
+ // |0 .. 2| 3 |4 .. 6
+ enum { CallConvMask = 0x7 };
+ enum { NoReturnMask = 0x8 };
+ enum { RegParmMask = ~(CallConvMask | NoReturnMask),
+ RegParmOffset = 4 };
+
+ unsigned char Bits;
+
+ ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {}
+
+ friend class FunctionType;
+
public:
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading an AST file for example).
- ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
- NoReturn(noReturn), RegParm(regParm), CC(cc) {}
+ ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) {
+ Bits = ((unsigned) cc) |
+ (noReturn ? NoReturnMask : 0) |
+ (regParm << RegParmOffset);
+ }
// Constructor with all defaults. Use when for example creating a
// function know to use defaults.
- ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {}
+ ExtInfo() : Bits(0) {}
- bool getNoReturn() const { return NoReturn; }
- unsigned getRegParm() const { return RegParm; }
- CallingConv getCC() const { return CC; }
+ bool getNoReturn() const { return Bits & NoReturnMask; }
+ unsigned getRegParm() const { return Bits >> RegParmOffset; }
+ CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
- bool operator==(const ExtInfo &Other) const {
- return getNoReturn() == Other.getNoReturn() &&
- getRegParm() == Other.getRegParm() &&
- getCC() == Other.getCC();
+ bool operator==(ExtInfo Other) const {
+ return Bits == Other.Bits;
}
- bool operator!=(const ExtInfo &Other) const {
- return !(*this == Other);
+ bool operator!=(ExtInfo Other) const {
+ return Bits != Other.Bits;
}
// Note that we don't have setters. That is by design, use
// the following with methods instead of mutating these objects.
ExtInfo withNoReturn(bool noReturn) const {
- return ExtInfo(noReturn, getRegParm(), getCC());
+ if (noReturn)
+ return ExtInfo(Bits | NoReturnMask);
+ else
+ return ExtInfo(Bits & ~NoReturnMask);
}
ExtInfo withRegParm(unsigned RegParm) const {
- return ExtInfo(getNoReturn(), RegParm, getCC());
+ return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset));
}
ExtInfo withCallingConv(CallingConv cc) const {
- return ExtInfo(getNoReturn(), getRegParm(), cc);
+ return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
}
- private:
- // True if we have __attribute__((noreturn))
- bool NoReturn;
- // The value passed to __attribute__((regparm(x)))
- unsigned RegParm;
- // The calling convention as specified via
- // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
- CallingConv CC;
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Bits);
+ }
};
protected:
- FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
- unsigned typeQuals, QualType Canonical, bool Dependent,
- const ExtInfo &Info)
- : Type(tc, Canonical, Dependent),
- SubClassData(SubclassInfo), TypeQuals(typeQuals),
- NoReturn(Info.getNoReturn()),
- RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}
- bool getSubClassData() const { return SubClassData; }
- unsigned getTypeQuals() const { return TypeQuals; }
+ FunctionType(TypeClass tc, QualType res, bool variadic,
+ unsigned typeQuals, RefQualifierKind RefQualifier,
+ QualType Canonical, bool Dependent,
+ bool VariablyModified, bool ContainsUnexpandedParameterPack,
+ ExtInfo Info)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack),
+ ResultType(res) {
+ FunctionTypeBits.ExtInfo = Info.Bits;
+ FunctionTypeBits.Variadic = variadic;
+ FunctionTypeBits.TypeQuals = typeQuals;
+ FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier);
+ }
+ bool isVariadic() const { return FunctionTypeBits.Variadic; }
+ unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
+
+ RefQualifierKind getRefQualifier() const {
+ return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
+ }
+
public:
QualType getResultType() const { return ResultType; }
- unsigned getRegParmType() const { return RegParm; }
- bool getNoReturnAttr() const { return NoReturn; }
- CallingConv getCallConv() const { return (CallingConv)CallConv; }
- ExtInfo getExtInfo() const {
- return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv);
- }
+ unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
+ bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
+ CallingConv getCallConv() const { return getExtInfo().getCC(); }
+ ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
/// \brief Determine the type of an expression that calls a function of
/// this type.
@@ -1972,15 +2365,13 @@ public:
/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
- FunctionNoProtoType(QualType Result, QualType Canonical,
- const ExtInfo &Info)
- : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
- /*Dependent=*/false, Info) {}
+ FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
+ : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical,
+ /*Dependent=*/false, Result->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false, Info) {}
+
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
// No additional state past what FunctionType provides.
@@ -1991,10 +2382,8 @@ public:
Profile(ID, getResultType(), getExtInfo());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
- const ExtInfo &Info) {
- ID.AddInteger(Info.getCC());
- ID.AddInteger(Info.getRegParm());
- ID.AddInteger(Info.getNoReturn());
+ ExtInfo Info) {
+ Info.Profile(ID);
ID.AddPointer(ResultType.getAsOpaquePtr());
}
@@ -2010,36 +2399,37 @@ public:
/// exception specification, but this specification is not part of the canonical
/// type.
class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
- /// hasAnyDependentType - Determine whether there are any dependent
- /// types within the arguments passed in.
- static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) {
+public:
+ /// ExtProtoInfo - Extra information about a function prototype.
+ struct ExtProtoInfo {
+ ExtProtoInfo() :
+ Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false),
+ TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {}
+
+ FunctionType::ExtInfo ExtInfo;
+ bool Variadic;
+ bool HasExceptionSpec;
+ bool HasAnyExceptionSpec;
+ unsigned char TypeQuals;
+ RefQualifierKind RefQualifier;
+ unsigned NumExceptions;
+ const QualType *Exceptions;
+ };
+
+private:
+ /// \brief Determine whether there are any argument types that
+ /// contain an unexpanded parameter pack.
+ static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray,
+ unsigned numArgs) {
for (unsigned Idx = 0; Idx < numArgs; ++Idx)
- if (ArgArray[Idx]->isDependentType())
- return true;
+ if (ArgArray[Idx]->containsUnexpandedParameterPack())
+ return true;
return false;
}
- FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
- bool isVariadic, unsigned typeQuals, bool hasExs,
- bool hasAnyExs, const QualType *ExArray,
- unsigned numExs, QualType Canonical,
- const ExtInfo &Info)
- : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
- (Result->isDependentType() ||
- hasAnyDependentType(ArgArray, numArgs)),
- Info),
- NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
- AnyExceptionSpec(hasAnyExs) {
- // Fill in the trailing argument array.
- QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
- for (unsigned i = 0; i != numArgs; ++i)
- ArgInfo[i] = ArgArray[i];
- // Fill in the exception array.
- QualType *Ex = ArgInfo + numArgs;
- for (unsigned i = 0; i != numExs; ++i)
- Ex[i] = ExArray[i];
- }
+ FunctionProtoType(QualType result, const QualType *args, unsigned numArgs,
+ QualType canonical, const ExtProtoInfo &epi);
/// NumArgs - The number of arguments this function has, not counting '...'.
unsigned NumArgs : 20;
@@ -2048,10 +2438,10 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
unsigned NumExceptions : 10;
/// HasExceptionSpec - Whether this function has an exception spec at all.
- bool HasExceptionSpec : 1;
+ unsigned HasExceptionSpec : 1;
- /// AnyExceptionSpec - Whether this function has a throw(...) spec.
- bool AnyExceptionSpec : 1;
+ /// HasAnyExceptionSpec - Whether this function has a throw(...) spec.
+ unsigned HasAnyExceptionSpec : 1;
/// ArgInfo - There is an variable size array after the class in memory that
/// holds the argument types.
@@ -2061,9 +2451,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
unsigned getNumArgs() const { return NumArgs; }
QualType getArgType(unsigned i) const {
@@ -2071,8 +2458,21 @@ public:
return arg_type_begin()[i];
}
+ ExtProtoInfo getExtProtoInfo() const {
+ ExtProtoInfo EPI;
+ EPI.ExtInfo = getExtInfo();
+ EPI.Variadic = isVariadic();
+ EPI.HasExceptionSpec = hasExceptionSpec();
+ EPI.HasAnyExceptionSpec = hasAnyExceptionSpec();
+ EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
+ EPI.RefQualifier = getRefQualifier();
+ EPI.NumExceptions = NumExceptions;
+ EPI.Exceptions = exception_begin();
+ return EPI;
+ }
+
bool hasExceptionSpec() const { return HasExceptionSpec; }
- bool hasAnyExceptionSpec() const { return AnyExceptionSpec; }
+ bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; }
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!");
@@ -2083,9 +2483,24 @@ public:
getNumExceptions() == 0;
}
- bool isVariadic() const { return getSubClassData(); }
+ using FunctionType::isVariadic;
+
+ /// \brief Determines whether this function prototype contains a
+ /// parameter pack at the end.
+ ///
+ /// A function template whose last parameter is a parameter pack can be
+ /// called with an arbitrary number of arguments, much like a variadic
+ /// function. However,
+ bool isTemplateVariadic() const;
+
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+
+ /// \brief Retrieve the ref-qualifier associated with this function type.
+ RefQualifierKind getRefQualifier() const {
+ return FunctionType::getRefQualifier();
+ }
+
typedef const QualType *arg_type_iterator;
arg_type_iterator arg_type_begin() const {
return reinterpret_cast<const QualType *>(this+1);
@@ -2112,10 +2527,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys, unsigned NumArgs,
- bool isVariadic, unsigned TypeQuals,
- bool hasExceptionSpec, bool anyExceptionSpec,
- unsigned NumExceptions, exception_iterator Exs,
- const ExtInfo &ExtInfo);
+ const ExtProtoInfo &EPI);
};
@@ -2127,7 +2539,8 @@ class UnresolvedUsingType : public Type {
UnresolvedUsingTypenameDecl *Decl;
UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
- : Type(UnresolvedUsing, QualType(), true),
+ : Type(UnresolvedUsing, QualType(), true, false,
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
@@ -2156,7 +2569,8 @@ class TypedefType : public Type {
TypedefDecl *Decl;
protected:
TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
- : Type(tc, can, can->isDependentType()),
+ : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(const_cast<TypedefDecl*>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
@@ -2165,14 +2579,6 @@ public:
TypedefDecl *getDecl() const { return Decl; }
- /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
- /// potentially looking through *all* consecutive typedefs. This returns the
- /// sum of the type qualifiers, so if you have:
- /// typedef const int A;
- /// typedef volatile A B;
- /// looking through the typedefs for B will give you "const volatile A".
- QualType LookThroughTypedefs() const;
-
bool isSugared() const { return true; }
QualType desugar() const;
@@ -2208,10 +2614,10 @@ public:
/// of this class via TypeOfExprType nodes.
class DependentTypeOfExprType
: public TypeOfExprType, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
public:
- DependentTypeOfExprType(ASTContext &Context, Expr *E)
+ DependentTypeOfExprType(const ASTContext &Context, Expr *E)
: TypeOfExprType(E), Context(Context) { }
bool isSugared() const { return false; }
@@ -2221,7 +2627,7 @@ public:
Profile(ID, Context, getUnderlyingExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expr *E);
};
@@ -2229,7 +2635,9 @@ public:
class TypeOfType : public Type {
QualType TOType;
TypeOfType(QualType T, QualType can)
- : Type(TypeOf, can, T->isDependentType()), TOType(T) {
+ : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(),
+ T->containsUnexpandedParameterPack()),
+ TOType(T) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
friend class ASTContext; // ASTContext creates these.
@@ -2279,10 +2687,10 @@ public:
/// canonical, dependent types, only. Clients will only see instances
/// of this class via DecltypeType nodes.
class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
public:
- DependentDecltypeType(ASTContext &Context, Expr *E);
+ DependentDecltypeType(const ASTContext &Context, Expr *E);
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2291,7 +2699,7 @@ public:
Profile(ID, Context, getUnderlyingExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expr *E);
};
@@ -2303,8 +2711,6 @@ class TagType : public Type {
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
- virtual Linkage getLinkageImpl() const;
-
public:
TagDecl *getDecl() const;
@@ -2340,10 +2746,6 @@ public:
// const, it needs to return false.
bool hasConstFields() const { return false; }
- // FIXME: RecordType needs to check when it is created that all fields are in
- // the same address space, and return that.
- unsigned getAddressSpace() const { return 0; }
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2376,20 +2778,107 @@ public:
static bool classof(const EnumType *) { return true; }
};
+/// AttributedType - An attributed type is a type to which a type
+/// attribute has been applied. The "modified type" is the
+/// fully-sugared type to which the attributed type was applied;
+/// generally it is not canonically equivalent to the attributed type.
+/// The "equivalent type" is the minimally-desugared type which the
+/// type is canonically equivalent to.
+///
+/// For example, in the following attributed type:
+/// int32_t __attribute__((vector_size(16)))
+/// - the modified type is the TypedefType for int32_t
+/// - the equivalent type is VectorType(16, int32_t)
+/// - the canonical type is VectorType(16, int)
+class AttributedType : public Type, public llvm::FoldingSetNode {
+public:
+ // It is really silly to have yet another attribute-kind enum, but
+ // clang::attr::Kind doesn't currently cover the pure type attrs.
+ enum Kind {
+ // Expression operand.
+ attr_address_space,
+ attr_regparm,
+ attr_vector_size,
+ attr_neon_vector_type,
+ attr_neon_polyvector_type,
+
+ FirstExprOperandKind = attr_address_space,
+ LastExprOperandKind = attr_neon_polyvector_type,
+
+ // Enumerated operand (string or keyword).
+ attr_objc_gc,
+
+ FirstEnumOperandKind = attr_objc_gc,
+ LastEnumOperandKind = attr_objc_gc,
+
+ // No operand.
+ attr_noreturn,
+ attr_cdecl,
+ attr_fastcall,
+ attr_stdcall,
+ attr_thiscall,
+ attr_pascal
+ };
+
+private:
+ QualType ModifiedType;
+ QualType EquivalentType;
+
+ friend class ASTContext; // creates these
+
+ AttributedType(QualType canon, Kind attrKind,
+ QualType modified, QualType equivalent)
+ : Type(Attributed, canon, canon->isDependentType(),
+ canon->isVariablyModifiedType(),
+ canon->containsUnexpandedParameterPack()),
+ ModifiedType(modified), EquivalentType(equivalent) {
+ AttributedTypeBits.AttrKind = attrKind;
+ }
+
+public:
+ Kind getAttrKind() const {
+ return static_cast<Kind>(AttributedTypeBits.AttrKind);
+ }
+
+ QualType getModifiedType() const { return ModifiedType; }
+ QualType getEquivalentType() const { return EquivalentType; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getEquivalentType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
+ QualType modified, QualType equivalent) {
+ ID.AddInteger(attrKind);
+ ID.AddPointer(modified.getAsOpaquePtr());
+ ID.AddPointer(equivalent.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Attributed;
+ }
+ static bool classof(const AttributedType *T) { return true; }
+};
+
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
unsigned Depth : 15;
- unsigned Index : 16;
unsigned ParameterPack : 1;
+ unsigned Index : 16;
IdentifierInfo *Name;
TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
QualType Canon)
- : Type(TemplateTypeParm, Canon, /*Dependent=*/true),
- Depth(D), Index(I), ParameterPack(PP), Name(N) { }
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(N) { }
TemplateTypeParmType(unsigned D, unsigned I, bool PP)
- : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
- Depth(D), Index(I), ParameterPack(PP), Name(0) { }
+ : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(0) { }
friend class ASTContext; // ASTContext creates these
@@ -2433,7 +2922,9 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
const TemplateTypeParmType *Replaced;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
- : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()),
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
Replaced(Param) { }
friend class ASTContext;
@@ -2471,6 +2962,101 @@ public:
static bool classof(const SubstTemplateTypeParmType *T) { return true; }
};
+/// \brief Represents the result of substituting a set of types for a template
+/// type parameter pack.
+///
+/// When a pack expansion in the source code contains multiple parameter packs
+/// and those parameter packs correspond to different levels of template
+/// parameter lists, this type node is used to represent a template type
+/// parameter pack from an outer level, which has already had its argument pack
+/// substituted but that still lives within a pack expansion that itself
+/// could not be instantiated. When actually performing a substitution into
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType
+/// at the current pack substitution index.
+class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
+ /// \brief The original type parameter.
+ const TemplateTypeParmType *Replaced;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+ QualType Canon,
+ const TemplateArgument &ArgPack);
+
+ friend class ASTContext;
+
+public:
+ IdentifierInfo *getName() const { return Replaced->getName(); }
+
+ /// Gets the template parameter that was substituted for.
+ const TemplateTypeParmType *getReplacedParameter() const {
+ return Replaced;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == SubstTemplateTypeParmPack;
+ }
+ static bool classof(const SubstTemplateTypeParmPackType *T) { return true; }
+};
+
+/// \brief Represents a C++0x auto type.
+///
+/// These types are usually a placeholder for a deduced type. However, within
+/// templates and before the initializer is attached, there is no deduced type
+/// and an auto type is type-dependent and canonical.
+class AutoType : public Type, public llvm::FoldingSetNode {
+ AutoType(QualType DeducedType)
+ : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
+ /*Dependent=*/DeducedType.isNull(),
+ /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+ assert((DeducedType.isNull() || !DeducedType->isDependentType()) &&
+ "deduced a dependent type for auto");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ bool isSugared() const { return isDeduced(); }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ QualType getDeducedType() const {
+ return isDeduced() ? getCanonicalTypeInternal() : QualType();
+ }
+ bool isDeduced() const {
+ return !isDependentType();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDeducedType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Deduced) {
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Auto;
+ }
+ static bool classof(const AutoType *T) { return true; }
+};
+
/// \brief Represents the type of a template specialization as written
/// in the source code.
///
@@ -2516,7 +3102,8 @@ public:
/// enclosing the template arguments.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs,
- const PrintingPolicy &Policy);
+ const PrintingPolicy &Policy,
+ bool SkipBrackets = false);
static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
unsigned NumArgs,
@@ -2556,14 +3143,14 @@ public:
}
QualType desugar() const { return getCanonicalTypeInternal(); }
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Ctx) {
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Template, getArgs(), NumArgs, Ctx);
}
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs,
- ASTContext &Context);
+ const ASTContext &Context);
static bool classof(const Type *T) {
return T->getTypeClass() == TemplateSpecialization;
@@ -2607,7 +3194,9 @@ class InjectedClassNameType : public Type {
// currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
- : Type(InjectedClassName, QualType(), true),
+ : Type(InjectedClassName, QualType(), /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(D), InjectedType(TST) {
assert(isa<TemplateSpecializationType>(TST));
assert(!TST.hasQualifiers());
@@ -2666,19 +3255,18 @@ enum ElaboratedTypeKeyword {
/// Also provides a few static helpers for converting and printing
/// elaborated type keyword and tag type kind enumerations.
class TypeWithKeyword : public Type {
- /// Keyword - Encodes an ElaboratedTypeKeyword enumeration constant.
- unsigned Keyword : 3;
-
protected:
TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc,
- QualType Canonical, bool dependent)
- : Type(tc, Canonical, dependent), Keyword(Keyword) {}
+ QualType Canonical, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack) {
+ TypeWithKeywordBits.Keyword = Keyword;
+ }
public:
- virtual ~TypeWithKeyword(); // pin vtable to Type.cpp
-
ElaboratedTypeKeyword getKeyword() const {
- return static_cast<ElaboratedTypeKeyword>(Keyword);
+ return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
}
/// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST)
@@ -2730,7 +3318,9 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
QualType NamedType, QualType CanonType)
: TypeWithKeyword(Keyword, Elaborated, CanonType,
- NamedType->isDependentType()),
+ NamedType->isDependentType(),
+ NamedType->isVariablyModifiedType(),
+ NamedType->containsUnexpandedParameterPack()),
NNS(NNS), NamedType(NamedType) {
assert(!(Keyword == ETK_None && NNS == 0) &&
"ElaboratedType cannot have elaborated type keyword "
@@ -2790,7 +3380,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, QualType CanonType)
- : TypeWithKeyword(Keyword, DependentName, CanonType, true),
+ : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
NNS(NNS), Name(Name) {
assert(NNS->isDependent() &&
"DependentNameType requires a dependent nested-name-specifier");
@@ -2799,8 +3391,6 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
public:
- virtual ~DependentNameType();
-
/// \brief Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
@@ -2867,8 +3457,6 @@ class DependentTemplateSpecializationType :
friend class ASTContext; // ASTContext creates these
public:
- virtual ~DependentTemplateSpecializationType();
-
NestedNameSpecifier *getQualifier() const { return NNS; }
const IdentifierInfo *getIdentifier() const { return Name; }
@@ -2889,12 +3477,12 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) {
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs());
}
static void Profile(llvm::FoldingSetNodeID &ID,
- ASTContext &Context,
+ const ASTContext &Context,
ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *Qualifier,
const IdentifierInfo *Name,
@@ -2909,6 +3497,88 @@ public:
}
};
+/// \brief Represents a pack expansion of types.
+///
+/// Pack expansions are part of C++0x variadic templates. A pack
+/// expansion contains a pattern, which itself contains one or more
+/// "unexpanded" parameter packs. When instantiated, a pack expansion
+/// produces a series of types, each instantiated from the pattern of
+/// the expansion, where the Ith instantiation of the pattern uses the
+/// Ith arguments bound to each of the unexpanded parameter packs. The
+/// pack expansion is considered to "expand" these unexpanded
+/// parameter packs.
+///
+/// \code
+/// template<typename ...Types> struct tuple;
+///
+/// template<typename ...Types>
+/// struct tuple_of_references {
+/// typedef tuple<Types&...> type;
+/// };
+/// \endcode
+///
+/// Here, the pack expansion \c Types&... is represented via a
+/// PackExpansionType whose pattern is Types&.
+class PackExpansionType : public Type, public llvm::FoldingSetNode {
+ /// \brief The pattern of the pack expansion.
+ QualType Pattern;
+
+ /// \brief The number of expansions that this pack expansion will
+ /// generate when substituted (+1), or indicates that
+ ///
+ /// This field will only have a non-zero value when some of the parameter
+ /// packs that occur within the pattern have been substituted but others have
+ /// not.
+ unsigned NumExpansions;
+
+ PackExpansionType(QualType Pattern, QualType Canon,
+ llvm::Optional<unsigned> NumExpansions)
+ : Type(PackExpansion, Canon, /*Dependent=*/true,
+ /*VariableModified=*/Pattern->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Pattern(Pattern),
+ NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the pattern of this pack expansion, which is the
+ /// type that will be repeatedly instantiated when instantiating the
+ /// pack expansion itself.
+ QualType getPattern() const { return Pattern; }
+
+ /// \brief Retrieve the number of expansions that this pack expansion will
+ /// generate, if known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPattern(), getNumExpansions());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions) {
+ ID.AddPointer(Pattern.getAsOpaquePtr());
+ ID.AddBoolean(NumExpansions);
+ if (NumExpansions)
+ ID.AddInteger(*NumExpansions);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == PackExpansion;
+ }
+ static bool classof(const PackExpansionType *T) {
+ return true;
+ }
+};
+
/// ObjCObjectType - Represents a class type in Objective C.
/// Every Objective C type is a combination of a base type and a
/// list of protocols.
@@ -2930,19 +3600,15 @@ public:
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
- // Pad the bit count up so that NumProtocols is 2-byte aligned
- unsigned : BitsRemainingInType - 16;
-
- /// \brief The number of protocols stored after the
- /// ObjCObjectPointerType node.
- ///
- /// These protocols are those written directly on the type. If
- /// protocol qualifiers ever become additive, the iterators will
- /// get kindof complicated.
- ///
- /// In the canonical object type, these are sorted alphabetically
- /// and uniqued.
- unsigned NumProtocols : 16;
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the ObjCObjectPointerType node.
+ //
+ // These protocols are those written directly on the type. If
+ // protocol qualifiers ever become additive, the iterators will need
+ // to get kindof complicated.
+ //
+ // In the canonical object type, these are sorted alphabetically
+ // and uniqued.
/// Either a BuiltinType or an InterfaceType or sugar for either.
QualType BaseType;
@@ -2959,13 +3625,11 @@ protected:
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
- : Type(ObjCInterface, QualType(), false),
- NumProtocols(0),
- BaseType(QualType(this_(), 0)) {}
+ : Type(ObjCInterface, QualType(), false, false, false),
+ BaseType(QualType(this_(), 0)) {
+ ObjCObjectTypeBits.NumProtocols = 0;
+ }
-protected:
- Linkage getLinkageImpl() const; // key function
-
public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
@@ -3006,7 +3670,7 @@ public:
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
- unsigned getNumProtocols() const { return NumProtocols; }
+ unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
/// \brief Fetch a protocol by index.
ObjCProtocolDecl *getProtocol(unsigned I) const {
@@ -3072,6 +3736,7 @@ class ObjCInterfaceType : public ObjCObjectType {
: ObjCObjectType(Nonce_ObjCInterface),
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
+
public:
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3117,13 +3782,10 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical, false),
+ : Type(ObjCObjectPointer, Canonical, false, false, false),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
/// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
@@ -3152,7 +3814,7 @@ public:
/// would return 'A1P<Q>' (and we'd have to make iterating over
/// qualifiers more complicated).
const ObjCObjectType *getObjectType() const {
- return PointeeType->getAs<ObjCObjectType>();
+ return PointeeType->castAs<ObjCObjectType>();
}
/// getInterfaceType - If this pointer points to an Objective C
@@ -3238,177 +3900,154 @@ public:
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
- ASTContext *Context;
-
public:
- QualifierCollector(Qualifiers Qs = Qualifiers())
- : Qualifiers(Qs), Context(0) {}
- QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers())
- : Qualifiers(Qs), Context(&Context) {}
-
- void setContext(ASTContext &C) { Context = &C; }
+ QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {}
/// Collect any qualifiers on the given type and return an
- /// unqualified type.
- const Type *strip(QualType QT) {
- addFastQualifiers(QT.getLocalFastQualifiers());
- if (QT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = QT.getExtQualsUnsafe();
- Context = &EQ->getContext();
- addQualifiers(EQ->getQualifiers());
- return EQ->getBaseType();
- }
- return QT.getTypePtrUnsafe();
+ /// unqualified type. The qualifiers are assumed to be consistent
+ /// with those already in the type.
+ const Type *strip(QualType type) {
+ addFastQualifiers(type.getLocalFastQualifiers());
+ if (!type.hasLocalNonFastQualifiers())
+ return type.getTypePtrUnsafe();
+
+ const ExtQuals *extQuals = type.getExtQualsUnsafe();
+ addConsistentQualifiers(extQuals->getQualifiers());
+ return extQuals->getBaseType();
}
/// Apply the collected qualifiers to the given type.
- QualType apply(QualType QT) const;
+ QualType apply(const ASTContext &Context, QualType QT) const;
/// Apply the collected qualifiers to the given type.
- QualType apply(const Type* T) const;
-
+ QualType apply(const ASTContext &Context, const Type* T) const;
};
// Inline function definitions.
+inline const Type *QualType::getTypePtr() const {
+ return getCommonPtr()->BaseType;
+}
+
+inline const Type *QualType::getTypePtrOrNull() const {
+ return (isNull() ? 0 : getCommonPtr()->BaseType);
+}
+
+inline SplitQualType QualType::split() const {
+ if (!hasLocalNonFastQualifiers())
+ return SplitQualType(getTypePtrUnsafe(),
+ Qualifiers::fromFastMask(getLocalFastQualifiers()));
+
+ const ExtQuals *eq = getExtQualsUnsafe();
+ Qualifiers qs = eq->getQualifiers();
+ qs.addFastQualifiers(getLocalFastQualifiers());
+ return SplitQualType(eq->getBaseType(), qs);
+}
+
+inline Qualifiers QualType::getLocalQualifiers() const {
+ Qualifiers Quals;
+ if (hasLocalNonFastQualifiers())
+ Quals = getExtQualsUnsafe()->getQualifiers();
+ Quals.addFastQualifiers(getLocalFastQualifiers());
+ return Quals;
+}
+
+inline Qualifiers QualType::getQualifiers() const {
+ Qualifiers quals = getCommonPtr()->CanonicalType.getLocalQualifiers();
+ quals.addFastQualifiers(getLocalFastQualifiers());
+ return quals;
+}
+
+inline unsigned QualType::getCVRQualifiers() const {
+ unsigned cvr = getCommonPtr()->CanonicalType.getLocalCVRQualifiers();
+ cvr |= getLocalCVRQualifiers();
+ return cvr;
+}
+
+inline QualType QualType::getCanonicalType() const {
+ QualType canon = getCommonPtr()->CanonicalType;
+ return canon.withFastQualifiers(getLocalFastQualifiers());
+}
+
inline bool QualType::isCanonical() const {
- const Type *T = getTypePtr();
- if (hasLocalQualifiers())
- return T->isCanonicalUnqualified() && !isa<ArrayType>(T);
- return T->isCanonicalUnqualified();
+ return getTypePtr()->isCanonicalUnqualified();
}
inline bool QualType::isCanonicalAsParam() const {
+ if (!isCanonical()) return false;
if (hasLocalQualifiers()) return false;
+
const Type *T = getTypePtr();
- return T->isCanonicalUnqualified() &&
- !isa<FunctionType>(T) && !isa<ArrayType>(T);
+ if (T->isVariablyModifiedType() && T->hasSizedVLAType())
+ return false;
+
+ return !isa<FunctionType>(T) && !isa<ArrayType>(T);
}
inline bool QualType::isConstQualified() const {
return isLocalConstQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified();
+ getCommonPtr()->CanonicalType.isLocalConstQualified();
}
inline bool QualType::isRestrictQualified() const {
return isLocalRestrictQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified();
+ getCommonPtr()->CanonicalType.isLocalRestrictQualified();
}
inline bool QualType::isVolatileQualified() const {
return isLocalVolatileQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified();
+ getCommonPtr()->CanonicalType.isLocalVolatileQualified();
}
inline bool QualType::hasQualifiers() const {
return hasLocalQualifiers() ||
- getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers();
-}
-
-inline Qualifiers QualType::getQualifiers() const {
- Qualifiers Quals = getLocalQualifiers();
- Quals.addQualifiers(
- getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers());
- return Quals;
-}
-
-inline unsigned QualType::getCVRQualifiers() const {
- return getLocalCVRQualifiers() |
- getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers();
+ getCommonPtr()->CanonicalType.hasLocalQualifiers();
}
-/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this
-/// type, returns them. Otherwise, if this is an array type, recurses
-/// on the element type until some qualifiers have been found or a non-array
-/// type reached.
-inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const {
- if (unsigned Quals = getCVRQualifiers())
- return Quals;
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getCVRQualifiersThroughArrayTypes();
- return 0;
+inline QualType QualType::getUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return QualType(getTypePtr(), 0);
+
+ return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0);
}
-inline void QualType::removeConst() {
- removeFastQualifiers(Qualifiers::Const);
+inline SplitQualType QualType::getSplitUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return split();
+
+ return getSplitUnqualifiedTypeImpl(*this);
+}
+
+inline void QualType::removeLocalConst() {
+ removeLocalFastQualifiers(Qualifiers::Const);
}
-inline void QualType::removeRestrict() {
- removeFastQualifiers(Qualifiers::Restrict);
+inline void QualType::removeLocalRestrict() {
+ removeLocalFastQualifiers(Qualifiers::Restrict);
}
-inline void QualType::removeVolatile() {
- QualifierCollector Qc;
- const Type *Ty = Qc.strip(*this);
- if (Qc.hasVolatile()) {
- Qc.removeVolatile();
- *this = Qc.apply(Ty);
- }
+inline void QualType::removeLocalVolatile() {
+ removeLocalFastQualifiers(Qualifiers::Volatile);
}
-inline void QualType::removeCVRQualifiers(unsigned Mask) {
+inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits");
+ assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask);
// Fast path: we don't need to touch the slow qualifiers.
- if (!(Mask & ~Qualifiers::FastMask)) {
- removeFastQualifiers(Mask);
- return;
- }
-
- QualifierCollector Qc;
- const Type *Ty = Qc.strip(*this);
- Qc.removeCVRQualifiers(Mask);
- *this = Qc.apply(Ty);
+ removeLocalFastQualifiers(Mask);
}
/// getAddressSpace - Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
- if (hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = getExtQualsUnsafe();
- if (EQ->hasAddressSpace())
- return EQ->getAddressSpace();
- }
-
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = CT.getExtQualsUnsafe();
- if (EQ->hasAddressSpace())
- return EQ->getAddressSpace();
- }
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getAddressSpace();
- if (const RecordType *RT = dyn_cast<RecordType>(CT))
- return RT->getAddressSpace();
- return 0;
+ return getQualifiers().getAddressSpace();
}
/// getObjCGCAttr - Return the gc attribute of this type.
inline Qualifiers::GC QualType::getObjCGCAttr() const {
- if (hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = getExtQualsUnsafe();
- if (EQ->hasObjCGCAttr())
- return EQ->getObjCGCAttr();
- }
-
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = CT.getExtQualsUnsafe();
- if (EQ->hasObjCGCAttr())
- return EQ->getObjCGCAttr();
- }
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getObjCGCAttr();
- if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>())
- return PT->getPointeeType().getObjCGCAttr();
- // We most look at all pointer types, not just pointer to interface types.
- if (const PointerType *PT = CT->getAs<PointerType>())
- return PT->getPointeeType().getObjCGCAttr();
- return Qualifiers::GCNone;
+ return getQualifiers().getObjCGCAttr();
}
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
@@ -3436,26 +4075,18 @@ inline bool Qualifiers::isSupersetOf(Qualifiers Other) const {
/// is more qualified than "const int", "volatile int", and
/// "int". However, it is not more qualified than "const volatile
/// int".
-inline bool QualType::isMoreQualifiedThan(QualType Other) const {
- // FIXME: work on arbitrary qualifiers
- unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
- unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
- if (getAddressSpace() != Other.getAddressSpace())
- return false;
- return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals;
+inline bool QualType::isMoreQualifiedThan(QualType other) const {
+ Qualifiers myQuals = getQualifiers();
+ Qualifiers otherQuals = other.getQualifiers();
+ return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals));
}
/// isAtLeastAsQualifiedAs - Determine whether this type is at last
/// as qualified as the Other type. For example, "const volatile
/// int" is at least as qualified as "const int", "volatile int",
/// "int", and "const volatile int".
-inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
- // FIXME: work on arbitrary qualifiers
- unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
- unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
- if (getAddressSpace() != Other.getAddressSpace())
- return false;
- return (MyQuals | OtherQuals) == MyQuals;
+inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
+ return getQualifiers().compatiblyIncludes(other.getQualifiers());
}
/// getNonReferenceType - If Type is a reference type (e.g., const
@@ -3496,7 +4127,7 @@ inline bool Type::isRValueReferenceType() const {
return isa<RValueReferenceType>(CanonicalType);
}
inline bool Type::isFunctionPointerType() const {
- if (const PointerType* T = getAs<PointerType>())
+ if (const PointerType *T = getAs<PointerType>())
return T->getPointeeType()->isFunctionType();
else
return false;
@@ -3531,9 +4162,15 @@ inline bool Type::isVariableArrayType() const {
inline bool Type::isDependentSizedArrayType() const {
return isa<DependentSizedArrayType>(CanonicalType);
}
+inline bool Type::isBuiltinType() const {
+ return isa<BuiltinType>(CanonicalType);
+}
inline bool Type::isRecordType() const {
return isa<RecordType>(CanonicalType);
}
+inline bool Type::isEnumeralType() const {
+ return isa<EnumType>(CanonicalType);
+}
inline bool Type::isAnyComplexType() const {
return isa<ComplexType>(CanonicalType);
}
@@ -3586,10 +4223,6 @@ inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);
}
-inline bool Type::isBuiltinType() const {
- return getAs<BuiltinType>();
-}
-
inline bool Type::isSpecificBuiltinType(unsigned K) const {
if (const BuiltinType *BT = getAs<BuiltinType>())
if (BT->getKind() == (BuiltinType::Kind) K)
@@ -3597,6 +4230,12 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const {
return false;
}
+inline bool Type::isPlaceholderType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ return BT->isPlaceholderType();
+ return false;
+}
+
/// \brief Determines whether this is a type for which one can define
/// an overloaded operator.
inline bool Type::isOverloadableType() const {
@@ -3612,6 +4251,13 @@ inline bool Type::hasObjCPointerRepresentation() const {
return isObjCObjectPointerType();
}
+inline const Type *Type::getBaseElementTypeUnsafe() const {
+ const Type *type = this;
+ while (const ArrayType *arrayType = type->getAsArrayTypeUnsafe())
+ type = arrayType->getElementType().getTypePtr();
+ return type;
+}
+
/// Insertion operator for diagnostics. This allows sending QualType's into a
/// diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -3658,6 +4304,35 @@ template <typename T> const T *Type::getAs() const {
return cast<T>(getUnqualifiedDesugaredType());
}
+inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
+ // If this is directly an array type, return it.
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this))
+ return arr;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<ArrayType>(CanonicalType))
+ return 0;
+
+ // If this is a typedef for the type, strip the typedef off without
+ // losing all typedef information.
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
+template <typename T> const T *Type::castAs() const {
+ ArrayType_cannot_be_used_with_getAs<T> at;
+ (void) at;
+
+ assert(isa<T>(CanonicalType));
+ if (const T *ty = dyn_cast<T>(this)) return ty;
+ return cast<T>(getUnqualifiedDesugaredType());
+}
+
+inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
+ assert(isa<ArrayType>(CanonicalType));
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr;
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index f1c64bd95977..c7f5ee76330c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -20,6 +20,7 @@
#include "clang/Basic/Specifiers.h"
namespace clang {
+ class ASTContext;
class ParmVarDecl;
class TypeSourceInfo;
class UnqualTypeLoc;
@@ -38,7 +39,7 @@ class TypeLoc {
protected:
// The correctness of this relies on the property that, for Type *Ty,
// QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
- void *Ty;
+ const void *Ty;
void *Data;
public:
@@ -56,7 +57,7 @@ public:
TypeLoc() : Ty(0), Data(0) { }
TypeLoc(QualType ty, void *opaqueData)
: Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
- TypeLoc(Type *ty, void *opaqueData)
+ TypeLoc(const Type *ty, void *opaqueData)
: Ty(ty), Data(opaqueData) { }
TypeLocClass getTypeLocClass() const {
@@ -76,7 +77,7 @@ public:
return QualType::getFromOpaquePtr(Ty);
}
- Type *getTypePtr() const {
+ const Type *getTypePtr() const {
return QualType::getFromOpaquePtr(Ty).getTypePtr();
}
@@ -115,13 +116,36 @@ public:
/// \brief Skips past any qualifiers, if this is qualified.
UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header
+ TypeLoc IgnoreParens() const {
+ if (isa<ParenTypeLoc>(this))
+ return IgnoreParensImpl(*this);
+ return *this;
+ }
+
/// \brief Initializes this to state that every location in this
/// type is the given location.
///
/// This method exists to provide a simple transition for code that
/// relies on location-less types.
- void initialize(SourceLocation Loc) const {
- initializeImpl(*this, Loc);
+ void initialize(ASTContext &Context, SourceLocation Loc) const {
+ initializeImpl(Context, *this, Loc);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type.
+ void initializeFullCopy(TypeLoc Other) const {
+ assert(getType() == Other.getType());
+ size_t Size = getFullDataSize();
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type. The given size must be the full data
+ /// size.
+ void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+ assert(getType() == Other.getType());
+ assert(getFullDataSize() == Size);
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
}
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
@@ -135,8 +159,9 @@ public:
static bool classof(const TypeLoc *TL) { return true; }
private:
- static void initializeImpl(TypeLoc TL, SourceLocation Loc);
+ static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc);
static TypeLoc getNextTypeLocImpl(TypeLoc TL);
+ static TypeLoc IgnoreParensImpl(TypeLoc TL);
static SourceRange getLocalSourceRangeImpl(TypeLoc TL);
};
@@ -146,14 +171,14 @@ inline TypeLoc TypeSourceInfo::getTypeLoc() const {
}
/// \brief Wrapper of type source information for a type with
-/// no direct quqlaifiers.
+/// no direct qualifiers.
class UnqualTypeLoc : public TypeLoc {
public:
UnqualTypeLoc() {}
- UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
+ UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
- Type *getTypePtr() const {
- return reinterpret_cast<Type*>(Ty);
+ const Type *getTypePtr() const {
+ return reinterpret_cast<const Type*>(Ty);
}
TypeLocClass getTypeLocClass() const {
@@ -183,7 +208,7 @@ public:
/// Initializes the local data of this type source info block to
/// provide no information.
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
// do nothing
}
@@ -282,7 +307,7 @@ public:
return getNextTypeLoc(asDerived()->getInnerType());
}
- TypeClass *getTypePtr() const {
+ const TypeClass *getTypePtr() const {
return cast<TypeClass>(Base::getTypePtr());
}
@@ -355,7 +380,7 @@ public:
return true;
}
- TypeClass *getTypePtr() const {
+ const TypeClass *getTypePtr() const {
return cast<TypeClass>(Base::getTypePtr());
}
};
@@ -383,7 +408,7 @@ public:
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
}
@@ -484,7 +509,7 @@ public:
getWrittenBuiltinSpecs().ModeAttr = written;
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setBuiltinLoc(Loc);
if (needsExtraLocalData()) {
WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
@@ -568,6 +593,137 @@ class SubstTemplateTypeParmTypeLoc :
SubstTemplateTypeParmType> {
};
+ /// \brief Wrapper for substituted template type parameters.
+class SubstTemplateTypeParmPackTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ SubstTemplateTypeParmPackTypeLoc,
+ SubstTemplateTypeParmPackType> {
+};
+
+struct AttributedLocInfo {
+ union {
+ Expr *ExprOperand;
+
+ /// A raw SourceLocation.
+ unsigned EnumOperandLoc;
+ };
+
+ SourceRange OperandParens;
+
+ SourceLocation AttrLoc;
+};
+
+/// \brief Type source information for an attributed type.
+class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ AttributedTypeLoc,
+ AttributedType,
+ AttributedLocInfo> {
+public:
+ AttributedType::Kind getAttrKind() const {
+ return getTypePtr()->getAttrKind();
+ }
+
+ bool hasAttrExprOperand() const {
+ return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
+ getAttrKind() <= AttributedType::LastExprOperandKind);
+ }
+
+ bool hasAttrEnumOperand() const {
+ return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
+ getAttrKind() <= AttributedType::LastEnumOperandKind);
+ }
+
+ bool hasAttrOperand() const {
+ return hasAttrExprOperand() || hasAttrEnumOperand();
+ }
+
+ /// The modified type, which is generally canonically different from
+ /// the attribute type.
+ /// int main(int, char**) __attribute__((noreturn))
+ /// ~~~ ~~~~~~~~~~~~~
+ TypeLoc getModifiedLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ /// The location of the attribute name, i.e.
+ /// __attribute__((regparm(1000)))
+ /// ^~~~~~~
+ SourceLocation getAttrNameLoc() const {
+ return getLocalData()->AttrLoc;
+ }
+ void setAttrNameLoc(SourceLocation loc) {
+ getLocalData()->AttrLoc = loc;
+ }
+
+ /// The attribute's expression operand, if it has one.
+ /// void *cur_thread __attribute__((address_space(21)))
+ /// ^~
+ Expr *getAttrExprOperand() const {
+ assert(hasAttrExprOperand());
+ return getLocalData()->ExprOperand;
+ }
+ void setAttrExprOperand(Expr *e) {
+ assert(hasAttrExprOperand());
+ getLocalData()->ExprOperand = e;
+ }
+
+ /// The location of the attribute's enumerated operand, if it has one.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^~~~
+ SourceLocation getAttrEnumOperandLoc() const {
+ assert(hasAttrEnumOperand());
+ return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
+ }
+ void setAttrEnumOperandLoc(SourceLocation loc) {
+ assert(hasAttrEnumOperand());
+ getLocalData()->EnumOperandLoc = loc.getRawEncoding();
+ }
+
+ /// The location of the parentheses around the operand, if there is
+ /// an operand.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^ ^
+ SourceRange getAttrOperandParensRange() const {
+ assert(hasAttrOperand());
+ return getLocalData()->OperandParens;
+ }
+ void setAttrOperandParensRange(SourceRange range) {
+ assert(hasAttrOperand());
+ getLocalData()->OperandParens = range;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ // Note that this does *not* include the range of the attribute
+ // enclosure, e.g.:
+ // __attribute__((foo(bar)))
+ // ^~~~~~~~~~~~~~~ ~~
+ // or
+ // [[foo(bar)]]
+ // ^~ ~~
+ // That enclosure doesn't necessarily belong to a single attribute
+ // anyway.
+ SourceRange range(getAttrNameLoc());
+ if (hasAttrOperand())
+ range.setEnd(getAttrOperandParensRange().getEnd());
+ return range;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation loc) {
+ setAttrNameLoc(loc);
+ if (hasAttrExprOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrExprOperand(0);
+ } else if (hasAttrEnumOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrEnumOperandLoc(loc);
+ }
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getModifiedType();
+ }
+};
+
struct ObjCProtocolListLocInfo {
SourceLocation LAngleLoc;
@@ -638,7 +794,7 @@ public:
return SourceRange(getLAngleLoc(), getRAngleLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
@@ -682,11 +838,51 @@ public:
return SourceRange(getNameLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
}
};
+struct ParenLocInfo {
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+};
+
+class ParenTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
+ ParenLocInfo> {
+public:
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+
+ TypeLoc getInnerLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getInnerType();
+ }
+};
+
struct PointerLikeLocInfo {
SourceLocation StarLoc;
@@ -712,7 +908,7 @@ public:
return SourceRange(getSigilLoc(), getSigilLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
}
@@ -812,6 +1008,7 @@ public:
struct FunctionLocInfo {
SourceLocation LParenLoc, RParenLoc;
+ bool TrailingReturn;
};
/// \brief Wrapper for source info for functions.
@@ -819,11 +1016,6 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
FunctionTypeLoc,
FunctionType,
FunctionLocInfo> {
- // ParmVarDecls* are stored after Info, one for each argument.
- ParmVarDecl **getParmArray() const {
- return (ParmVarDecl**) getExtraLocalData();
- }
-
public:
SourceLocation getLParenLoc() const {
return getLocalData()->LParenLoc;
@@ -839,6 +1031,18 @@ public:
getLocalData()->RParenLoc = Loc;
}
+ bool getTrailingReturn() const {
+ return getLocalData()->TrailingReturn;
+ }
+ void setTrailingReturn(bool Trailing) {
+ getLocalData()->TrailingReturn = Trailing;
+ }
+
+ // ParmVarDecls* are stored after Info, one for each argument.
+ ParmVarDecl **getParmArray() const {
+ return (ParmVarDecl**) getExtraLocalData();
+ }
+
unsigned getNumArgs() const {
if (isa<FunctionNoProtoType>(getTypePtr()))
return 0;
@@ -855,9 +1059,10 @@ public:
return SourceRange(getLParenLoc(), getRParenLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLParenLoc(Loc);
setRParenLoc(Loc);
+ setTrailingReturn(false);
for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
setArg(i, NULL);
}
@@ -928,7 +1133,7 @@ public:
return SourceRange(getLBracketLoc(), getRBracketLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLBracketLoc(Loc);
setRBracketLoc(Loc);
setSizeExpr(NULL);
@@ -997,9 +1202,6 @@ public:
return getTypePtr()->getNumArgs();
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
-#ifndef NDEBUG
- AI.validateForArgument(getTypePtr()->getArg(i));
-#endif
getArgInfos()[i] = AI;
}
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
@@ -1033,47 +1235,18 @@ public:
return SourceRange(getTemplateNameLoc(), getRAngleLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLAngleLoc(Loc);
setRAngleLoc(Loc);
setTemplateNameLoc(Loc);
- initializeArgLocs(getNumArgs(), getTypePtr()->getArgs(),
+ initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
getArgInfos(), Loc);
}
- static void initializeArgLocs(unsigned NumArgs,
+ static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
const TemplateArgument *Args,
TemplateArgumentLocInfo *ArgInfos,
- SourceLocation Loc) {
- for (unsigned i = 0, e = NumArgs; i != e; ++i) {
- TemplateArgumentLocInfo Info;
-#ifndef NDEBUG
- // If asserts are enabled, be sure to initialize the argument
- // loc with the right kind of pointer.
- switch (Args[i].getKind()) {
- case TemplateArgument::Expression:
- case TemplateArgument::Declaration:
- Info = TemplateArgumentLocInfo((Expr*) 0);
- break;
-
- case TemplateArgument::Type:
- Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0);
- break;
-
- case TemplateArgument::Template:
- Info = TemplateArgumentLocInfo(SourceRange(Loc), Loc);
- break;
-
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- case TemplateArgument::Null:
- // K_None is fine.
- break;
- }
-#endif
- ArgInfos[i] = Info;
- }
- }
+ SourceLocation Loc);
unsigned getExtraLocalDataSize() const {
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
@@ -1168,7 +1341,7 @@ public:
return SourceRange(getTypeofLoc(), getRParenLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setTypeofLoc(Loc);
setLParenLoc(Loc);
setRParenLoc(Loc);
@@ -1208,6 +1381,11 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DecltypeType> {
};
+class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ AutoTypeLoc,
+ AutoType> {
+};
+
struct ElaboratedLocInfo {
SourceLocation KeywordLoc;
SourceRange QualifierRange;
@@ -1242,7 +1420,7 @@ public:
return getQualifierRange();
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
}
@@ -1307,7 +1485,7 @@ public:
memcpy(Data, Loc.Data, size);
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
setNameLoc(Loc);
@@ -1368,9 +1546,6 @@ public:
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
-#ifndef NDEBUG
- AI.validateForArgument(getTypePtr()->getArg(i));
-#endif
getArgInfos()[i] = AI;
}
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
@@ -1394,13 +1569,13 @@ public:
memcpy(Data, Loc.Data, size);
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
setNameLoc(Loc);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
- TemplateSpecializationTypeLoc::initializeArgLocs(getNumArgs(),
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
getTypePtr()->getArgs(),
getArgInfos(), Loc);
}
@@ -1415,6 +1590,40 @@ private:
}
};
+
+struct PackExpansionTypeLocInfo {
+ SourceLocation EllipsisLoc;
+};
+
+class PackExpansionTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc,
+ PackExpansionType, PackExpansionTypeLocInfo> {
+public:
+ SourceLocation getEllipsisLoc() const {
+ return this->getLocalData()->EllipsisLoc;
+ }
+
+ void setEllipsisLoc(SourceLocation Loc) {
+ this->getLocalData()->EllipsisLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getEllipsisLoc(), getEllipsisLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setEllipsisLoc(Loc);
+ }
+
+ TypeLoc getPatternLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getPattern();
+ }
+};
+
}
#endif
diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h
deleted file mode 100644
index 880af267f324..000000000000
--- a/include/clang/AST/TypeLocBuilder.h
+++ /dev/null
@@ -1,155 +0,0 @@
-//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This files defines TypeLocBuilder, a class for building TypeLocs
-// bottom-up.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H
-#define LLVM_CLANG_AST_TYPELOCBUILDER_H
-
-#include "clang/AST/TypeLoc.h"
-#include "llvm/ADT/SmallVector.h"
-#include "clang/AST/ASTContext.h"
-
-namespace clang {
-
-class TypeLocBuilder {
- enum { InlineCapacity = 8 * sizeof(SourceLocation) };
-
- /// The underlying location-data buffer. Data grows from the end
- /// of the buffer backwards.
- char *Buffer;
-
- /// The capacity of the current buffer.
- size_t Capacity;
-
- /// The index of the first occupied byte in the buffer.
- size_t Index;
-
-#ifndef NDEBUG
- /// The last type pushed on this builder.
- QualType LastTy;
-#endif
-
- /// The inline buffer.
- char InlineBuffer[InlineCapacity];
-
- public:
- TypeLocBuilder()
- : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
- {}
-
- ~TypeLocBuilder() {
- if (Buffer != InlineBuffer)
- delete[] Buffer;
- }
-
- /// Ensures that this buffer has at least as much capacity as described.
- void reserve(size_t Requested) {
- if (Requested > Capacity)
- // For now, match the request exactly.
- grow(Requested);
- }
-
- /// Pushes a copy of the given TypeLoc onto this builder. The builder
- /// must be empty for this to work.
- void pushFullCopy(TypeLoc L) {
-#ifndef NDEBUG
- assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder");
- LastTy = L.getNextTypeLoc().getType();
-#endif
- assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder");
-
- unsigned Size = L.getFullDataSize();
- TypeLoc Copy = pushImpl(L.getType(), Size);
- memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
- }
-
- /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
- /// previously retrieved from this builder.
- TypeSpecTypeLoc pushTypeSpec(QualType T) {
- size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
- return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
- }
-
- /// Resets this builder to the newly-initialized state.
- void clear() {
-#ifndef NDEBUG
- LastTy = QualType();
-#endif
- Index = Capacity;
- }
-
- /// Pushes space for a new TypeLoc of the given type. Invalidates
- /// any TypeLocs previously retrieved from this builder.
- template <class TyLocType> TyLocType push(QualType T) {
- size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
- return cast<TyLocType>(pushImpl(T, LocalSize));
- }
-
- /// Creates a TypeSourceInfo for the given type.
- TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
-#ifndef NDEBUG
- assert(T == LastTy && "type doesn't match last type pushed!");
-#endif
-
- size_t FullDataSize = Capacity - Index;
- TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
- memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
- return DI;
- }
-
-private:
- TypeLoc pushImpl(QualType T, size_t LocalSize) {
-#ifndef NDEBUG
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
- assert(TLast == LastTy &&
- "mismatch between last type and new type's inner type");
- LastTy = T;
-#endif
-
- // If we need to grow, grow by a factor of 2.
- if (LocalSize > Index) {
- size_t RequiredCapacity = Capacity + (LocalSize - Index);
- size_t NewCapacity = Capacity * 2;
- while (RequiredCapacity > NewCapacity)
- NewCapacity *= 2;
- grow(NewCapacity);
- }
-
- Index -= LocalSize;
-
- return TypeLoc(T, &Buffer[Index]);
- }
-
- /// Grow to the given capacity.
- void grow(size_t NewCapacity) {
- assert(NewCapacity > Capacity);
-
- // Allocate the new buffer and copy the old data into it.
- char *NewBuffer = new char[NewCapacity];
- unsigned NewIndex = Index + NewCapacity - Capacity;
- memcpy(&NewBuffer[NewIndex],
- &Buffer[Index],
- Capacity - Index);
-
- if (Buffer != InlineBuffer)
- delete[] Buffer;
-
- Buffer = NewBuffer;
- Capacity = NewCapacity;
- Index = NewIndex;
- }
-};
-
-}
-
-#endif
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 9cb56861a9ef..b2591cc0fbac 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -79,6 +79,7 @@ ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)
TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
+NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
@@ -87,12 +88,16 @@ ABSTRACT_TYPE(Tag, Type)
TYPE(Record, TagType)
TYPE(Enum, TagType)
NON_CANONICAL_TYPE(Elaborated, Type)
+NON_CANONICAL_TYPE(Attributed, Type)
DEPENDENT_TYPE(TemplateTypeParm, Type)
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
+DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
DEPENDENT_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(DependentName, Type)
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
+DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
index 5c9c5285a248..c52926b1fc31 100644
--- a/include/clang/AST/TypeVisitor.h
+++ b/include/clang/AST/TypeVisitor.h
@@ -19,12 +19,13 @@
namespace clang {
#define DISPATCH(CLASS) \
- return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T))
+ return static_cast<ImplClass*>(this)-> \
+ Visit##CLASS(static_cast<const CLASS*>(T))
template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
- RetTy Visit(Type *T) {
+ RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
default: assert(0 && "Unknown type class!");
@@ -36,13 +37,13 @@ public:
// If the implementation chooses not to implement a certain visit method, fall
// back on superclass.
-#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { \
+#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
DISPATCH(PARENT); \
}
#include "clang/AST/TypeNodes.def"
// Base case, ignore it. :)
- RetTy VisitType(Type*) { return RetTy(); }
+ RetTy VisitType(const Type*) { return RetTy(); }
};
#undef DISPATCH