diff options
Diffstat (limited to 'include/clang/AST')
86 files changed, 0 insertions, 62513 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h deleted file mode 100644 index e58c219..0000000 --- a/include/clang/AST/APValue.h +++ /dev/null @@ -1,452 +0,0 @@ -//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_APVALUE_H -#define LLVM_CLANG_AST_APVALUE_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/PointerUnion.h" - -namespace clang { - class AddrLabelExpr; - class ASTContext; - class CharUnits; - class DiagnosticBuilder; - class Expr; - class FieldDecl; - class Decl; - class ValueDecl; - class CXXRecordDecl; - class QualType; - -/// APValue - This class implements a discriminated union of [uninitialized] -/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], -/// [Vector: N * APValue], [Array: N * APValue] -class APValue { - typedef llvm::APSInt APSInt; - typedef llvm::APFloat APFloat; -public: - enum ValueKind { - Uninitialized, - Int, - Float, - ComplexInt, - ComplexFloat, - LValue, - Vector, - Array, - Struct, - Union, - MemberPointer, - AddrLabelDiff - }; - typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; - typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; - union LValuePathEntry { - /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item - /// in the path. An opaque value of type BaseOrMemberType. - void *BaseOrMember; - /// ArrayIndex - The array index of the next item in the path. - uint64_t ArrayIndex; - }; - struct NoLValuePath {}; - struct UninitArray {}; - struct UninitStruct {}; -private: - ValueKind Kind; - - struct ComplexAPSInt { - APSInt Real, Imag; - ComplexAPSInt() : Real(1), Imag(1) {} - }; - struct ComplexAPFloat { - APFloat Real, Imag; - ComplexAPFloat() : Real(0.0), Imag(0.0) {} - }; - struct LV; - struct Vec { - APValue *Elts; - unsigned NumElts; - Vec() : Elts(nullptr), NumElts(0) {} - ~Vec() { delete[] Elts; } - }; - struct Arr { - APValue *Elts; - unsigned NumElts, ArrSize; - Arr(unsigned NumElts, unsigned ArrSize); - ~Arr(); - }; - struct StructData { - APValue *Elts; - unsigned NumBases; - unsigned NumFields; - StructData(unsigned NumBases, unsigned NumFields); - ~StructData(); - }; - struct UnionData { - const FieldDecl *Field; - APValue *Value; - UnionData(); - ~UnionData(); - }; - struct AddrLabelDiffData { - const AddrLabelExpr* LHSExpr; - const AddrLabelExpr* RHSExpr; - }; - struct MemberPointerData; - - // We ensure elsewhere that Data is big enough for LV and MemberPointerData. - typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, - ComplexAPFloat, Vec, Arr, StructData, - UnionData, AddrLabelDiffData> DataType; - static const size_t DataSize = sizeof(DataType); - - DataType Data; - -public: - APValue() : Kind(Uninitialized) {} - explicit APValue(APSInt I) : Kind(Uninitialized) { - MakeInt(); setInt(std::move(I)); - } - explicit APValue(APFloat F) : Kind(Uninitialized) { - MakeFloat(); setFloat(std::move(F)); - } - explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { - MakeVector(); setVector(E, N); - } - APValue(APSInt R, APSInt I) : Kind(Uninitialized) { - MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); - } - APValue(APFloat R, APFloat I) : Kind(Uninitialized) { - MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); - } - APValue(const APValue &RHS); - APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } - APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) - : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, N, CallIndex); - } - APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, - bool OnePastTheEnd, unsigned CallIndex) - : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex); - } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { - MakeArray(InitElts, Size); - } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { - MakeStruct(B, M); - } - explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(Uninitialized) { - MakeUnion(); setUnion(D, V); - } - APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { - MakeMemberPointer(Member, IsDerivedMember, Path); - } - APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) - : Kind(Uninitialized) { - MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); - } - - ~APValue() { - MakeUninit(); - } - - /// \brief Returns whether the object performed allocations. - /// - /// If APValues are constructed via placement new, \c needsCleanup() - /// indicates whether the destructor must be called in order to correctly - /// free all allocated memory. - bool needsCleanup() const; - - /// \brief Swaps the contents of this and the given APValue. - void swap(APValue &RHS); - - ValueKind getKind() const { return Kind; } - bool isUninit() const { return Kind == Uninitialized; } - bool isInt() const { return Kind == Int; } - bool isFloat() const { return Kind == Float; } - bool isComplexInt() const { return Kind == ComplexInt; } - bool isComplexFloat() const { return Kind == ComplexFloat; } - bool isLValue() const { return Kind == LValue; } - bool isVector() const { return Kind == Vector; } - bool isArray() const { return Kind == Array; } - bool isStruct() const { return Kind == Struct; } - bool isUnion() const { return Kind == Union; } - bool isMemberPointer() const { return Kind == MemberPointer; } - bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } - - void dump() const; - void dump(raw_ostream &OS) const; - - void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; - std::string getAsString(ASTContext &Ctx, QualType Ty) const; - - APSInt &getInt() { - assert(isInt() && "Invalid accessor"); - return *(APSInt*)(char*)Data.buffer; - } - const APSInt &getInt() const { - return const_cast<APValue*>(this)->getInt(); - } - - APFloat &getFloat() { - assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(char*)Data.buffer; - } - const APFloat &getFloat() const { - return const_cast<APValue*>(this)->getFloat(); - } - - APSInt &getComplexIntReal() { - assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Real; - } - const APSInt &getComplexIntReal() const { - return const_cast<APValue*>(this)->getComplexIntReal(); - } - - APSInt &getComplexIntImag() { - assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; - } - const APSInt &getComplexIntImag() const { - return const_cast<APValue*>(this)->getComplexIntImag(); - } - - APFloat &getComplexFloatReal() { - assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Real; - } - const APFloat &getComplexFloatReal() const { - return const_cast<APValue*>(this)->getComplexFloatReal(); - } - - APFloat &getComplexFloatImag() { - assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; - } - const APFloat &getComplexFloatImag() const { - return const_cast<APValue*>(this)->getComplexFloatImag(); - } - - const LValueBase getLValueBase() const; - CharUnits &getLValueOffset(); - const CharUnits &getLValueOffset() const { - return const_cast<APValue*>(this)->getLValueOffset(); - } - bool isLValueOnePastTheEnd() const; - bool hasLValuePath() const; - ArrayRef<LValuePathEntry> getLValuePath() const; - unsigned getLValueCallIndex() const; - - APValue &getVectorElt(unsigned I) { - assert(isVector() && "Invalid accessor"); - assert(I < getVectorLength() && "Index out of range"); - return ((Vec*)(char*)Data.buffer)->Elts[I]; - } - const APValue &getVectorElt(unsigned I) const { - return const_cast<APValue*>(this)->getVectorElt(I); - } - unsigned getVectorLength() const { - assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data.buffer)->NumElts; - } - - APValue &getArrayInitializedElt(unsigned I) { - assert(isArray() && "Invalid accessor"); - assert(I < getArrayInitializedElts() && "Index out of range"); - return ((Arr*)(char*)Data.buffer)->Elts[I]; - } - const APValue &getArrayInitializedElt(unsigned I) const { - return const_cast<APValue*>(this)->getArrayInitializedElt(I); - } - bool hasArrayFiller() const { - return getArrayInitializedElts() != getArraySize(); - } - APValue &getArrayFiller() { - assert(isArray() && "Invalid accessor"); - assert(hasArrayFiller() && "No array filler"); - return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; - } - const APValue &getArrayFiller() const { - return const_cast<APValue*>(this)->getArrayFiller(); - } - unsigned getArrayInitializedElts() const { - assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data.buffer)->NumElts; - } - unsigned getArraySize() const { - assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data.buffer)->ArrSize; - } - - unsigned getStructNumBases() const { - assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumBases; - } - unsigned getStructNumFields() const { - assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumFields; - } - APValue &getStructBase(unsigned i) { - assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[i]; - } - APValue &getStructField(unsigned i) { - assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; - } - const APValue &getStructBase(unsigned i) const { - return const_cast<APValue*>(this)->getStructBase(i); - } - const APValue &getStructField(unsigned i) const { - return const_cast<APValue*>(this)->getStructField(i); - } - - const FieldDecl *getUnionField() const { - assert(isUnion() && "Invalid accessor"); - return ((const UnionData*)(const char*)Data.buffer)->Field; - } - APValue &getUnionValue() { - assert(isUnion() && "Invalid accessor"); - return *((UnionData*)(char*)Data.buffer)->Value; - } - const APValue &getUnionValue() const { - return const_cast<APValue*>(this)->getUnionValue(); - } - - const ValueDecl *getMemberPointerDecl() const; - bool isMemberPointerToDerivedMember() const; - ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; - - const AddrLabelExpr* getAddrLabelDiffLHS() const { - assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; - } - const AddrLabelExpr* getAddrLabelDiffRHS() const { - assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; - } - - void setInt(APSInt I) { - assert(isInt() && "Invalid accessor"); - *(APSInt *)(char *)Data.buffer = std::move(I); - } - void setFloat(APFloat F) { - assert(isFloat() && "Invalid accessor"); - *(APFloat *)(char *)Data.buffer = std::move(F); - } - void setVector(const APValue *E, unsigned N) { - assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; - ((Vec*)(char*)Data.buffer)->NumElts = N; - for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; - } - void setComplexInt(APSInt R, APSInt I) { - assert(R.getBitWidth() == I.getBitWidth() && - "Invalid complex int (type mismatch)."); - assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); - } - void setComplexFloat(APFloat R, APFloat I) { - assert(&R.getSemantics() == &I.getSemantics() && - "Invalid complex float (type mismatch)."); - assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); - } - void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex); - void setLValue(LValueBase B, const CharUnits &O, - ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, - unsigned CallIndex); - void setUnion(const FieldDecl *Field, const APValue &Value) { - assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data.buffer)->Field = Field; - *((UnionData*)(char*)Data.buffer)->Value = Value; - } - void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, - const AddrLabelExpr* RHSExpr) { - ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; - ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; - } - - /// Assign by swapping from a copy of the RHS. - APValue &operator=(APValue RHS) { - swap(RHS); - return *this; - } - -private: - void DestroyDataAndMakeUninit(); - void MakeUninit() { - if (Kind != Uninitialized) - DestroyDataAndMakeUninit(); - } - void MakeInt() { - assert(isUninit() && "Bad state change"); - new ((void*)Data.buffer) APSInt(1); - Kind = Int; - } - void MakeFloat() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) APFloat(0.0); - Kind = Float; - } - void MakeVector() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) Vec(); - Kind = Vector; - } - void MakeComplexInt() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPSInt(); - Kind = ComplexInt; - } - void MakeComplexFloat() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPFloat(); - Kind = ComplexFloat; - } - void MakeLValue(); - void MakeArray(unsigned InitElts, unsigned Size); - void MakeStruct(unsigned B, unsigned M) { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) StructData(B, M); - Kind = Struct; - } - void MakeUnion() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) UnionData(); - Kind = Union; - } - void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef<const CXXRecordDecl*> Path); - void MakeAddrLabelDiff() { - assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data.buffer) AddrLabelDiffData(); - Kind = AddrLabelDiff; - } -}; - -} // end namespace clang. - -#endif diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h deleted file mode 100644 index 6db351d..0000000 --- a/include/clang/AST/AST.h +++ /dev/null @@ -1,28 +0,0 @@ -//===--- AST.h - "Umbrella" header for AST library --------------*- 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 interface to the AST classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_AST_H -#define LLVM_CLANG_AST_AST_H - -// This header exports all AST interfaces. -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/Type.h" - -#endif diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h deleted file mode 100644 index b2730e4..0000000 --- a/include/clang/AST/ASTConsumer.h +++ /dev/null @@ -1,159 +0,0 @@ -//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- 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 ASTConsumer class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTCONSUMER_H -#define LLVM_CLANG_AST_ASTCONSUMER_H - -#include "llvm/ADT/StringRef.h" - -namespace clang { - class ASTContext; - class CXXMethodDecl; - class CXXRecordDecl; - class Decl; - class DeclGroupRef; - class ASTMutationListener; - class ASTDeserializationListener; // layering violation because void* is ugly - class SemaConsumer; // layering violation required for safe SemaConsumer - class TagDecl; - class VarDecl; - class FunctionDecl; - class ImportDecl; - -/// ASTConsumer - This is an abstract interface that should be implemented by -/// clients that read ASTs. This abstraction layer allows the client to be -/// independent of the AST producer (e.g. parser vs AST dump file reader, etc). -class ASTConsumer { - /// \brief Whether this AST consumer also requires information about - /// semantic analysis. - bool SemaConsumer; - - friend class SemaConsumer; - -public: - ASTConsumer() : SemaConsumer(false) { } - - virtual ~ASTConsumer() {} - - /// Initialize - This is called to initialize the consumer, providing the - /// ASTContext. - virtual void Initialize(ASTContext &Context) {} - - /// HandleTopLevelDecl - Handle the specified top-level declaration. This is - /// called by the parser to process every top-level Decl*. - /// - /// \returns true to continue parsing, or false to abort parsing. - virtual bool HandleTopLevelDecl(DeclGroupRef D); - - /// \brief This callback is invoked each time an inline method definition is - /// completed. - virtual void HandleInlineMethodDefinition(CXXMethodDecl *D) {} - - /// HandleInterestingDecl - Handle the specified interesting declaration. This - /// is called by the AST reader when deserializing things that might interest - /// the consumer. The default implementation forwards to HandleTopLevelDecl. - virtual void HandleInterestingDecl(DeclGroupRef D); - - /// HandleTranslationUnit - This method is called when the ASTs for entire - /// translation unit have been parsed. - virtual void HandleTranslationUnit(ASTContext &Ctx) {} - - /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl - /// (e.g. struct, union, enum, class) is completed. This allows the client to - /// hack on the type, which can occur at any point in the file (because these - /// can be defined in declspecs). - virtual void HandleTagDeclDefinition(TagDecl *D) {} - - /// \brief This callback is invoked the first time each TagDecl is required to - /// be complete. - virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {} - - /// \brief Invoked when a function is implicitly instantiated. - /// Note that at this point point it does not have a body, its body is - /// instantiated at the end of the translation unit and passed to - /// HandleTopLevelDecl. - virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {} - - /// \brief Handle the specified top-level declaration that occurred inside - /// and ObjC container. - /// The default implementation ignored them. - virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); - - /// \brief Handle an ImportDecl that was implicitly created due to an - /// inclusion directive. - /// The default implementation passes it to HandleTopLevelDecl. - virtual void HandleImplicitImportDecl(ImportDecl *D); - - /// \brief Handle a pragma that appends to Linker Options. Currently this - /// only exists to support Microsoft's #pragma comment(linker, "/foo"). - virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {} - - /// \brief Handle a pragma that emits a mismatch identifier and value to the - /// object file for the linker to work with. Currently, this only exists to - /// support Microsoft's #pragma detect_mismatch. - virtual void HandleDetectMismatch(llvm::StringRef Name, - llvm::StringRef Value) {} - - /// \brief Handle a dependent library created by a pragma in the source. - /// Currently this only exists to support Microsoft's - /// #pragma comment(lib, "/foo"). - virtual void HandleDependentLibrary(llvm::StringRef Lib) {} - - /// CompleteTentativeDefinition - Callback invoked at the end of a translation - /// unit to notify the consumer that the given tentative definition should be - /// completed. - /// - /// The variable declaration itself will be a tentative - /// definition. If it had an incomplete array type, its type will - /// have already been changed to an array of size 1. However, the - /// declaration remains a tentative definition and has not been - /// modified by the introduction of an implicit zero initializer. - virtual void CompleteTentativeDefinition(VarDecl *D) {} - - /// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this - // variable has been instantiated. - virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {} - - /// \brief Callback involved at the end of a translation unit to - /// notify the consumer that a vtable for the given C++ class is - /// required. - /// - /// \param RD The class whose vtable was used. - virtual void HandleVTable(CXXRecordDecl *RD) {} - - /// \brief If the consumer is interested in entities getting modified after - /// their initial creation, it should return a pointer to - /// an ASTMutationListener here. - virtual ASTMutationListener *GetASTMutationListener() { return nullptr; } - - /// \brief If the consumer is interested in entities being deserialized from - /// AST files, it should return a pointer to a ASTDeserializationListener here - virtual ASTDeserializationListener *GetASTDeserializationListener() { - return nullptr; - } - - /// PrintStats - If desired, print any statistics. - virtual void PrintStats() {} - - /// \brief This callback is called for each function if the Parser was - /// initialized with \c SkipFunctionBodies set to \c true. - /// - /// \return \c true if the function's body should be skipped. The function - /// body may be parsed anyway if it is needed (for instance, if it contains - /// the code completion point or is constexpr). - virtual bool shouldSkipFunctionBody(Decl *D) { return true; } -}; - -} // end namespace clang. - -#endif diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h deleted file mode 100644 index b66009e..0000000 --- a/include/clang/AST/ASTContext.h +++ /dev/null @@ -1,2672 +0,0 @@ -//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the clang::ASTContext interface. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTCONTEXT_H -#define LLVM_CLANG_AST_ASTCONTEXT_H - -#include "clang/AST/ASTTypeTraits.h" -#include "clang/AST/CanonicalType.h" -#include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/Decl.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/PrettyPrinter.h" -#include "clang/AST/RawCommentList.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/SanitizerBlacklist.h" -#include "clang/Basic/VersionTuple.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/Support/Allocator.h" -#include <memory> -#include <vector> - -namespace llvm { - struct fltSemantics; -} - -namespace clang { - class FileManager; - class AtomicExpr; - class ASTRecordLayout; - class BlockExpr; - class CharUnits; - class DiagnosticsEngine; - class Expr; - class ASTMutationListener; - class IdentifierTable; - class MaterializeTemporaryExpr; - class SelectorTable; - class TargetInfo; - class CXXABI; - class MangleNumberingContext; - // Decls - class MangleContext; - class ObjCIvarDecl; - class ObjCPropertyDecl; - class UnresolvedSetIterator; - class UsingDecl; - class UsingShadowDecl; - class VTableContextBase; - - namespace Builtin { class Context; } - enum BuiltinTemplateKind : int; - - namespace comments { - class FullComment; - } - - struct TypeInfo { - uint64_t Width; - unsigned Align; - bool AlignIsRequired : 1; - TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {} - TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired) - : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} - }; - -/// \brief Holds long-lived AST nodes (such as types and decls) that can be -/// referred to throughout the semantic analysis of a file. -class ASTContext : public RefCountedBase<ASTContext> { - ASTContext &this_() { return *this; } - - mutable SmallVector<Type *, 0> Types; - mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; - mutable llvm::FoldingSet<ComplexType> ComplexTypes; - mutable llvm::FoldingSet<PointerType> PointerTypes; - mutable llvm::FoldingSet<AdjustedType> AdjustedTypes; - 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::ContextualFoldingSet<FunctionProtoType, ASTContext&> - 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; - mutable llvm::FoldingSet<ParenType> ParenTypes; - mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes; - mutable llvm::FoldingSet<DependentNameType> DependentNameTypes; - mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType, - ASTContext&> - DependentTemplateSpecializationTypes; - llvm::FoldingSet<PackExpansionType> PackExpansionTypes; - mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; - mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - mutable llvm::FoldingSet<AutoType> AutoTypes; - mutable llvm::FoldingSet<AtomicType> AtomicTypes; - llvm::FoldingSet<AttributedType> AttributedTypes; - - mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; - mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; - mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage> - SubstTemplateTemplateParms; - mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage, - ASTContext&> - SubstTemplateTemplateParmPacks; - - /// \brief The set of nested name specifiers. - /// - /// This set is managed by the NestedNameSpecifier class. - mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; - mutable NestedNameSpecifier *GlobalNestedNameSpecifier; - friend class NestedNameSpecifier; - - /// \brief A cache mapping from RecordDecls to ASTRecordLayouts. - /// - /// This is lazily created. This is intentionally not serialized. - mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> - ASTRecordLayouts; - mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> - ObjCLayouts; - - /// \brief A cache from types to size and alignment information. - typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap; - mutable TypeInfoMap MemoizedTypeInfo; - - /// \brief A cache mapping from CXXRecordDecls to key functions. - llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions; - - /// \brief Mapping from ObjCContainers to their ObjCImplementations. - llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; - - /// \brief Mapping from ObjCMethod to its duplicate declaration in the same - /// interface. - llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls; - - /// \brief Mapping from __block VarDecls to their copy initialization expr. - llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits; - - /// \brief Mapping from class scope functions specialization to their - /// template patterns. - llvm::DenseMap<const FunctionDecl*, FunctionDecl*> - ClassScopeSpecializationPattern; - - /// \brief Mapping from materialized temporaries with static storage duration - /// that appear in constant initializers to their evaluated values. These are - /// allocated in a std::map because their address must be stable. - llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *> - MaterializedTemporaryValues; - - /// \brief Representation of a "canonical" template template parameter that - /// is used in canonical template names. - class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { - TemplateTemplateParmDecl *Parm; - - public: - CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm) - : Parm(Parm) { } - - TemplateTemplateParmDecl *getParam() const { return Parm; } - - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); } - - static void Profile(llvm::FoldingSetNodeID &ID, - TemplateTemplateParmDecl *Parm); - }; - mutable llvm::FoldingSet<CanonicalTemplateTemplateParm> - CanonTemplateTemplateParms; - - TemplateTemplateParmDecl * - getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const; - - /// \brief The typedef for the __int128_t type. - mutable TypedefDecl *Int128Decl; - - /// \brief The typedef for the __uint128_t type. - mutable TypedefDecl *UInt128Decl; - - /// \brief The typedef for the __float128 stub type. - mutable TypeDecl *Float128StubDecl; - - /// \brief The typedef for the target specific predefined - /// __builtin_va_list type. - mutable TypedefDecl *BuiltinVaListDecl; - - /// The typedef for the predefined \c __builtin_ms_va_list type. - mutable TypedefDecl *BuiltinMSVaListDecl; - - /// \brief The typedef for the predefined \c id type. - mutable TypedefDecl *ObjCIdDecl; - - /// \brief The typedef for the predefined \c SEL type. - mutable TypedefDecl *ObjCSelDecl; - - /// \brief The typedef for the predefined \c Class type. - mutable TypedefDecl *ObjCClassDecl; - - /// \brief The typedef for the predefined \c Protocol class in Objective-C. - mutable ObjCInterfaceDecl *ObjCProtocolClassDecl; - - /// \brief The typedef for the predefined 'BOOL' type. - mutable TypedefDecl *BOOLDecl; - - // Typedefs which may be provided defining the structure of Objective-C - // pseudo-builtins - QualType ObjCIdRedefinitionType; - QualType ObjCClassRedefinitionType; - QualType ObjCSelRedefinitionType; - - /// The identifier 'NSObject'. - IdentifierInfo *NSObjectName = nullptr; - - /// The identifier 'NSCopying'. - IdentifierInfo *NSCopyingName = nullptr; - - /// The identifier '__make_integer_seq'. - mutable IdentifierInfo *MakeIntegerSeqName = nullptr; - - QualType ObjCConstantStringType; - mutable RecordDecl *CFConstantStringTypeDecl; - - mutable QualType ObjCSuperType; - - QualType ObjCNSStringType; - - /// \brief The typedef declaration for the Objective-C "instancetype" type. - TypedefDecl *ObjCInstanceTypeDecl; - - /// \brief The type for the C FILE type. - TypeDecl *FILEDecl; - - /// \brief The type for the C jmp_buf type. - TypeDecl *jmp_bufDecl; - - /// \brief The type for the C sigjmp_buf type. - TypeDecl *sigjmp_bufDecl; - - /// \brief The type for the C ucontext_t type. - TypeDecl *ucontext_tDecl; - - /// \brief Type for the Block descriptor for Blocks CodeGen. - /// - /// Since this is only used for generation of debug info, it is not - /// serialized. - mutable RecordDecl *BlockDescriptorType; - - /// \brief Type for the Block descriptor for Blocks CodeGen. - /// - /// Since this is only used for generation of debug info, it is not - /// serialized. - mutable RecordDecl *BlockDescriptorExtendedType; - - /// \brief Declaration for the CUDA cudaConfigureCall function. - FunctionDecl *cudaConfigureCallDecl; - - /// \brief Keeps track of all declaration attributes. - /// - /// Since so few decls have attrs, we keep them in a hash map instead of - /// wasting space in the Decl class. - llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs; - - /// \brief A mapping from non-redeclarable declarations in modules that were - /// merged with other declarations to the canonical declaration that they were - /// merged into. - llvm::DenseMap<Decl*, Decl*> MergedDecls; - - /// \brief A mapping from a defining declaration to a list of modules (other - /// than the owning module of the declaration) that contain merged - /// definitions of that entity. - llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules; - -public: - /// \brief A type synonym for the TemplateOrInstantiation mapping. - typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *> - TemplateOrSpecializationInfo; - -private: - - /// \brief A mapping to contain the template or declaration that - /// a variable declaration describes or was instantiated from, - /// respectively. - /// - /// For non-templates, this value will be NULL. For variable - /// declarations that describe a variable template, this will be a - /// pointer to a VarTemplateDecl. For static data members - /// of class template specializations, this will be the - /// MemberSpecializationInfo referring to the member variable that was - /// instantiated or specialized. Thus, the mapping will keep track of - /// the static data member templates from which static data members of - /// class template specializations were instantiated. - /// - /// Given the following example: - /// - /// \code - /// template<typename T> - /// struct X { - /// static T value; - /// }; - /// - /// template<typename T> - /// T X<T>::value = T(17); - /// - /// int *x = &X<int>::value; - /// \endcode - /// - /// This mapping will contain an entry that maps from the VarDecl for - /// X<int>::value to the corresponding VarDecl for X<T>::value (within the - /// class template X) and will be marked TSK_ImplicitInstantiation. - llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo> - TemplateOrInstantiation; - - /// \brief Keeps track of the declaration from which a UsingDecl was - /// created during instantiation. - /// - /// The source declaration is always a UsingDecl, an UnresolvedUsingValueDecl, - /// or an UnresolvedUsingTypenameDecl. - /// - /// For example: - /// \code - /// template<typename T> - /// struct A { - /// void f(); - /// }; - /// - /// template<typename T> - /// struct B : A<T> { - /// using A<T>::f; - /// }; - /// - /// template struct B<int>; - /// \endcode - /// - /// This mapping will contain an entry that maps from the UsingDecl in - /// B<int> to the UnresolvedUsingDecl in B<T>. - llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl; - - llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*> - InstantiatedFromUsingShadowDecl; - - llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; - - /// \brief Mapping that stores the methods overridden by a given C++ - /// member function. - /// - /// Since most C++ member functions aren't virtual and therefore - /// don't override anything, we store the overridden functions in - /// this map on the side rather than within the CXXMethodDecl structure. - typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector; - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; - - /// \brief Mapping from each declaration context to its corresponding - /// mangling numbering context (used for constructs like lambdas which - /// need to be consistently numbered for the mangler). - llvm::DenseMap<const DeclContext *, MangleNumberingContext *> - MangleNumberingContexts; - - /// \brief Side-table of mangling numbers for declarations which rarely - /// need them (like static local vars). - llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers; - llvm::DenseMap<const VarDecl *, unsigned> StaticLocalNumbers; - - /// \brief Mapping that stores parameterIndex values for ParmVarDecls when - /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. - typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable; - ParameterIndexTable ParamIndices; - - ImportDecl *FirstLocalImport; - ImportDecl *LastLocalImport; - - TranslationUnitDecl *TUDecl; - mutable ExternCContextDecl *ExternCContext; - mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; - - /// \brief The associated SourceManager object.a - SourceManager &SourceMgr; - - /// \brief The language options used to create the AST associated with - /// this ASTContext object. - LangOptions &LangOpts; - - /// \brief Blacklist object that is used by sanitizers to decide which - /// entities should not be instrumented. - std::unique_ptr<SanitizerBlacklist> SanitizerBL; - - /// \brief The allocator used to create AST objects. - /// - /// AST objects are never destructed; rather, all memory associated with the - /// AST objects will be released when the ASTContext itself is destroyed. - mutable llvm::BumpPtrAllocator BumpAlloc; - - /// \brief Allocator for partial diagnostics. - PartialDiagnostic::StorageAllocator DiagAllocator; - - /// \brief The current C++ ABI. - std::unique_ptr<CXXABI> ABI; - CXXABI *createCXXABI(const TargetInfo &T); - - /// \brief The logical -> physical address space map. - const LangAS::Map *AddrSpaceMap; - - /// \brief Address space map mangling must be used with language specific - /// address spaces (e.g. OpenCL/CUDA) - bool AddrSpaceMapMangling; - - friend class ASTDeclReader; - friend class ASTReader; - friend class ASTWriter; - friend class CXXRecordDecl; - - const TargetInfo *Target; - const TargetInfo *AuxTarget; - clang::PrintingPolicy PrintingPolicy; - -public: - IdentifierTable &Idents; - SelectorTable &Selectors; - Builtin::Context &BuiltinInfo; - mutable DeclarationNameTable DeclarationNames; - IntrusiveRefCntPtr<ExternalASTSource> ExternalSource; - ASTMutationListener *Listener; - - /// \brief Contains parents of a node. - typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector; - - /// \brief Maps from a node to its parents. This is used for nodes that have - /// pointer identity only, which are more common and we can save space by - /// only storing a unique pointer to them. - typedef llvm::DenseMap<const void *, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, - ParentVector *>> ParentMapPointers; - - /// Parent map for nodes without pointer identity. We store a full - /// DynTypedNode for all keys. - typedef llvm::DenseMap< - ast_type_traits::DynTypedNode, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, ParentVector *>> - ParentMapOtherNodes; - - /// Container for either a single DynTypedNode or for an ArrayRef to - /// DynTypedNode. For use with ParentMap. - class DynTypedNodeList { - typedef ast_type_traits::DynTypedNode DynTypedNode; - llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode, - ArrayRef<DynTypedNode>> Storage; - bool IsSingleNode; - - public: - DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { - new (Storage.buffer) DynTypedNode(N); - } - DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { - new (Storage.buffer) ArrayRef<DynTypedNode>(A); - } - - const ast_type_traits::DynTypedNode *begin() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) - ->begin(); - return reinterpret_cast<const DynTypedNode *>(Storage.buffer); - } - - const ast_type_traits::DynTypedNode *end() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) - ->end(); - return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1; - } - - size_t size() const { return end() - begin(); } - bool empty() const { return begin() == end(); } - const DynTypedNode &operator[](size_t N) const { - assert(N < size() && "Out of bounds!"); - return *(begin() + N); - } - }; - - /// \brief Returns the parents of the given node. - /// - /// Note that this will lazily compute the parents of all nodes - /// and store them for later retrieval. Thus, the first call is O(n) - /// in the number of AST nodes. - /// - /// Caveats and FIXMEs: - /// Calculating the parent map over all AST nodes will need to load the - /// full AST. This can be undesirable in the case where the full AST is - /// expensive to create (for example, when using precompiled header - /// preambles). Thus, there are good opportunities for optimization here. - /// One idea is to walk the given node downwards, looking for references - /// to declaration contexts - once a declaration context is found, compute - /// the parent map for the declaration context; if that can satisfy the - /// request, loading the whole AST can be avoided. Note that this is made - /// more complex by statements in templates having multiple parents - those - /// problems can be solved by building closure over the templated parts of - /// the AST, which also avoids touching large parts of the AST. - /// Additionally, we will want to add an interface to already give a hint - /// where to search for the parents, for example when looking at a statement - /// inside a certain function. - /// - /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, - /// NestedNameSpecifier or NestedNameSpecifierLoc. - template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) { - return getParents(ast_type_traits::DynTypedNode::create(Node)); - } - - DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node); - - const clang::PrintingPolicy &getPrintingPolicy() const { - return PrintingPolicy; - } - - void setPrintingPolicy(const clang::PrintingPolicy &Policy) { - PrintingPolicy = Policy; - } - - SourceManager& getSourceManager() { return SourceMgr; } - const SourceManager& getSourceManager() const { return SourceMgr; } - - llvm::BumpPtrAllocator &getAllocator() const { - return BumpAlloc; - } - - void *Allocate(size_t Size, unsigned Align = 8) const { - return BumpAlloc.Allocate(Size, Align); - } - template <typename T> T *Allocate(size_t Num = 1) const { - return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>())); - } - void Deallocate(void *Ptr) const { } - - /// Return the total amount of physical memory allocated for representing - /// AST nodes and type information. - size_t getASTAllocatedMemory() const { - return BumpAlloc.getTotalMemory(); - } - /// Return the total memory used for various side tables. - size_t getSideTableAllocatedMemory() const; - - PartialDiagnostic::StorageAllocator &getDiagAllocator() { - return DiagAllocator; - } - - const TargetInfo &getTargetInfo() const { return *Target; } - const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } - - /// getIntTypeForBitwidth - - /// sets integer QualTy according to specified details: - /// bitwidth, signed/unsigned. - /// Returns empty type if there is no appropriate target types. - QualType getIntTypeForBitwidth(unsigned DestWidth, - unsigned Signed) const; - /// getRealTypeForBitwidth - - /// sets floating point QualTy according to specified bitwidth. - /// Returns empty type if there is no appropriate target types. - QualType getRealTypeForBitwidth(unsigned DestWidth) const; - - bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; - - const LangOptions& getLangOpts() const { return LangOpts; } - - const SanitizerBlacklist &getSanitizerBlacklist() const { - return *SanitizerBL; - } - - DiagnosticsEngine &getDiagnostics() const; - - FullSourceLoc getFullLoc(SourceLocation Loc) const { - return FullSourceLoc(Loc,SourceMgr); - } - - /// \brief All comments in this translation unit. - RawCommentList Comments; - - /// \brief True if comments are already loaded from ExternalASTSource. - mutable bool CommentsLoaded; - - class RawCommentAndCacheFlags { - public: - enum Kind { - /// We searched for a comment attached to the particular declaration, but - /// didn't find any. - /// - /// getRaw() == 0. - NoCommentInDecl = 0, - - /// We have found a comment attached to this particular declaration. - /// - /// getRaw() != 0. - FromDecl, - - /// This declaration does not have an attached comment, and we have - /// searched the redeclaration chain. - /// - /// If getRaw() == 0, the whole redeclaration chain does not have any - /// comments. - /// - /// If getRaw() != 0, it is a comment propagated from other - /// redeclaration. - FromRedecl - }; - - Kind getKind() const LLVM_READONLY { - return Data.getInt(); - } - - void setKind(Kind K) { - Data.setInt(K); - } - - const RawComment *getRaw() const LLVM_READONLY { - return Data.getPointer(); - } - - void setRaw(const RawComment *RC) { - Data.setPointer(RC); - } - - const Decl *getOriginalDecl() const LLVM_READONLY { - return OriginalDecl; - } - - void setOriginalDecl(const Decl *Orig) { - OriginalDecl = Orig; - } - - private: - llvm::PointerIntPair<const RawComment *, 2, Kind> Data; - const Decl *OriginalDecl; - }; - - /// \brief Mapping from declarations to comments attached to any - /// redeclaration. - /// - /// Raw comments are owned by Comments list. This mapping is populated - /// lazily. - mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments; - - /// \brief Mapping from declarations to parsed comments attached to any - /// redeclaration. - mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments; - - /// \brief Return the documentation comment attached to a given declaration, - /// without looking into cache. - RawComment *getRawCommentForDeclNoCache(const Decl *D) const; - -public: - RawCommentList &getRawCommentList() { - return Comments; - } - - void addComment(const RawComment &RC) { - assert(LangOpts.RetainCommentsFromSystemHeaders || - !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin())); - Comments.addComment(RC, BumpAlloc); - } - - /// \brief Return the documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. - /// - /// \param OriginalDecl if not NULL, is set to declaration AST node that had - /// the comment, if the comment we found comes from a redeclaration. - const RawComment * - getRawCommentForAnyRedecl(const Decl *D, - const Decl **OriginalDecl = nullptr) const; - - /// Return parsed documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. - /// - /// \param PP the Preprocessor used with this TU. Could be NULL if - /// preprocessor is not available. - comments::FullComment *getCommentForDecl(const Decl *D, - const Preprocessor *PP) const; - - /// Return parsed documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. Does not look at any - /// redeclarations of the declaration. - comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const; - - comments::FullComment *cloneFullComment(comments::FullComment *FC, - const Decl *D) const; - -private: - mutable comments::CommandTraits CommentCommandTraits; - - /// \brief Iterator that visits import declarations. - class import_iterator { - ImportDecl *Import; - - public: - typedef ImportDecl *value_type; - typedef ImportDecl *reference; - typedef ImportDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; - - import_iterator() : Import() {} - explicit import_iterator(ImportDecl *Import) : Import(Import) {} - - reference operator*() const { return Import; } - pointer operator->() const { return Import; } - - import_iterator &operator++() { - Import = ASTContext::getNextLocalImport(Import); - return *this; - } - - import_iterator operator++(int) { - import_iterator Other(*this); - ++(*this); - return Other; - } - - friend bool operator==(import_iterator X, import_iterator Y) { - return X.Import == Y.Import; - } - - friend bool operator!=(import_iterator X, import_iterator Y) { - return X.Import != Y.Import; - } - }; - -public: - comments::CommandTraits &getCommentCommandTraits() const { - return CommentCommandTraits; - } - - /// \brief Retrieve the attributes for the given declaration. - AttrVec& getDeclAttrs(const Decl *D); - - /// \brief Erase the attributes corresponding to the given declaration. - void eraseDeclAttrs(const Decl *D); - - /// \brief If this variable is an instantiated static data member of a - /// class template specialization, returns the templated static data member - /// from which it was instantiated. - // FIXME: Remove ? - MemberSpecializationInfo *getInstantiatedFromStaticDataMember( - const VarDecl *Var); - - TemplateOrSpecializationInfo - getTemplateOrSpecializationInfo(const VarDecl *Var); - - FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD); - - void setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern); - - /// \brief Note that the static data member \p Inst is an instantiation of - /// the static data member template \p Tmpl of a class template. - void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, - TemplateSpecializationKind TSK, - SourceLocation PointOfInstantiation = SourceLocation()); - - void setTemplateOrSpecializationInfo(VarDecl *Inst, - TemplateOrSpecializationInfo TSI); - - /// \brief If the given using decl \p Inst is an instantiation of a - /// (possibly unresolved) using decl from a template instantiation, - /// return it. - NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst); - - /// \brief Remember that the using decl \p Inst is an instantiation - /// of the using decl \p Pattern of a class template. - void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern); - - void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, - UsingShadowDecl *Pattern); - UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); - - FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); - - void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); - - // Access to the set of methods overridden by the given C++ method. - typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator; - overridden_cxx_method_iterator - overridden_methods_begin(const CXXMethodDecl *Method) const; - - overridden_cxx_method_iterator - overridden_methods_end(const CXXMethodDecl *Method) const; - - unsigned overridden_methods_size(const CXXMethodDecl *Method) const; - - /// \brief Note that the given C++ \p Method overrides the given \p - /// Overridden method. - void addOverriddenMethod(const CXXMethodDecl *Method, - const CXXMethodDecl *Overridden); - - /// \brief Return C++ or ObjC overridden methods for the given \p Method. - /// - /// An ObjC method is considered to override any method in the class's - /// base classes, its protocols, or its categories' protocols, that has - /// the same selector and is of the same kind (class or instance). - /// A method in an implementation is not considered as overriding the same - /// method in the interface or its categories. - void getOverriddenMethods( - const NamedDecl *Method, - SmallVectorImpl<const NamedDecl *> &Overridden) const; - - /// \brief Notify the AST context that a new import declaration has been - /// parsed or implicitly created within this translation unit. - void addedLocalImportDecl(ImportDecl *Import); - - static ImportDecl *getNextLocalImport(ImportDecl *Import) { - return Import->NextLocalImport; - } - - typedef llvm::iterator_range<import_iterator> import_range; - import_range local_imports() const { - return import_range(import_iterator(FirstLocalImport), import_iterator()); - } - - Decl *getPrimaryMergedDecl(Decl *D) { - Decl *Result = MergedDecls.lookup(D); - return Result ? Result : D; - } - void setPrimaryMergedDecl(Decl *D, Decl *Primary) { - MergedDecls[D] = Primary; - } - - /// \brief Note that the definition \p ND has been merged into module \p M, - /// and should be visible whenever \p M is visible. - void mergeDefinitionIntoModule(NamedDecl *ND, Module *M, - bool NotifyListeners = true); - /// \brief Clean up the merged definition list. Call this if you might have - /// added duplicates into the list. - void deduplicateMergedDefinitonsFor(NamedDecl *ND); - - /// \brief Get the additional modules in which the definition \p Def has - /// been merged. - ArrayRef<Module*> getModulesWithMergedDefinition(NamedDecl *Def) { - auto MergedIt = MergedDefModules.find(Def); - if (MergedIt == MergedDefModules.end()) - return None; - return MergedIt->second; - } - - TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } - - ExternCContextDecl *getExternCContextDecl() const; - BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; - - // Builtin Types. - CanQualType VoidTy; - CanQualType BoolTy; - CanQualType CharTy; - CanQualType WCharTy; // [C++ 3.9.1p5]. - CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99. - CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions. - CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. - CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. - CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; - CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; - CanQualType UnsignedLongLongTy, UnsignedInt128Ty; - CanQualType FloatTy, DoubleTy, LongDoubleTy; - CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON - CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; - CanQualType VoidPtrTy, NullPtrTy; - CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; - CanQualType BuiltinFnTy; - CanQualType PseudoObjectTy, ARCUnbridgedCastTy; - CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; - CanQualType ObjCBuiltinBoolTy; - CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy; - CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy; - CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy; - CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy; - CanQualType OCLImage3dTy; - CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; - CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy; - CanQualType OMPArraySectionTy; - - // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. - mutable QualType AutoDeductTy; // Deduction against 'auto'. - mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. - - // Decl used to help define __builtin_va_list for some targets. - // The decl is built when constructing 'BuiltinVaListDecl'. - mutable Decl *VaListTagDecl; - - ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, - SelectorTable &sels, Builtin::Context &builtins); - - ~ASTContext(); - - /// \brief Attach an external AST source to the AST context. - /// - /// The external AST source provides the ability to load parts of - /// the abstract syntax tree as needed from some external storage, - /// e.g., a precompiled header. - void setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source); - - /// \brief Retrieve a pointer to the external AST source associated - /// 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 SmallVectorImpl<Type *>& getTypes() const { return Types; } - - BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, - const IdentifierInfo *II) const; - - /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl - /// declaration. - RecordDecl *buildImplicitRecord(StringRef Name, - RecordDecl::TagKind TK = TTK_Struct) const; - - /// \brief Create a new implicit TU-level typedef declaration. - TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const; - - /// \brief Retrieve the declaration for the 128-bit signed integer type. - TypedefDecl *getInt128Decl() const; - - /// \brief Retrieve the declaration for the 128-bit unsigned integer type. - TypedefDecl *getUInt128Decl() const; - - /// \brief Retrieve the declaration for a 128-bit float stub type. - TypeDecl *getFloat128StubType() const; - - //===--------------------------------------------------------------------===// - // Type Constructors - //===--------------------------------------------------------------------===// - -private: - /// \brief Return a type with extended qualifiers. - QualType getExtQualType(const Type *Base, Qualifiers Quals) const; - - QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; - -public: - /// \brief Return the uniqued reference to the type for an address space - /// qualified type with the specified type and address space. - /// - /// The resulting type has a union of the qualifiers from T and the address - /// space. If T already has an address space specifier, it is silently - /// replaced. - QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; - - /// \brief Return the uniqued reference to the type for an Objective-C - /// 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) const; - - /// \brief Return the uniqued reference to the type for a \c restrict - /// qualified type. - /// - /// The resulting type has a union of the qualifiers from \p T and - /// \c restrict. - QualType getRestrictType(QualType T) const { - return T.withFastQualifiers(Qualifiers::Restrict); - } - - /// \brief Return the uniqued reference to the type for a \c volatile - /// qualified type. - /// - /// The resulting type has a union of the qualifiers from \p T and - /// \c volatile. - QualType getVolatileType(QualType T) const { - return T.withFastQualifiers(Qualifiers::Volatile); - } - - /// \brief Return the uniqued reference to the type for a \c const - /// qualified type. - /// - /// The resulting type has a union of the qualifiers from \p T and \c const. - /// - /// It can be reasonably expected that this will always be equivalent to - /// calling T.withConst(). - QualType getConstType(QualType T) const { return T.withConst(); } - - /// \brief Change the ExtInfo on a function type. - const FunctionType *adjustFunctionType(const FunctionType *Fn, - FunctionType::ExtInfo EInfo); - - /// Adjust the given function result type. - CanQualType getCanonicalFunctionResultType(QualType ResultType) const; - - /// \brief Change the result type of a function type once it is deduced. - void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); - - /// \brief Change the exception specification on a function once it is - /// delay-parsed, instantiated, or computed. - void adjustExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExceptionSpecInfo &ESI, - bool AsWritten = false); - - /// \brief Return the uniqued reference to the type for a complex - /// number with the specified element type. - QualType getComplexType(QualType T) const; - CanQualType getComplexType(CanQualType T) const { - return CanQualType::CreateUnsafe(getComplexType((QualType) T)); - } - - /// \brief Return the uniqued reference to the type for a pointer to - /// the specified type. - QualType getPointerType(QualType T) const; - CanQualType getPointerType(CanQualType T) const { - return CanQualType::CreateUnsafe(getPointerType((QualType) T)); - } - - /// \brief Return the uniqued reference to a type adjusted from the original - /// type to a new type. - QualType getAdjustedType(QualType Orig, QualType New) const; - CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const { - return CanQualType::CreateUnsafe( - getAdjustedType((QualType)Orig, (QualType)New)); - } - - /// \brief Return the uniqued reference to the decayed version of the given - /// type. Can only be called on array and function types which decay to - /// pointer types. - QualType getDecayedType(QualType T) const; - CanQualType getDecayedType(CanQualType T) const { - return CanQualType::CreateUnsafe(getDecayedType((QualType) T)); - } - - /// \brief Return the uniqued reference to the atomic type for the specified - /// type. - QualType getAtomicType(QualType T) const; - - /// \brief Return the uniqued reference to the type for a block of the - /// specified type. - QualType getBlockPointerType(QualType T) const; - - /// Gets the struct used to keep track of the descriptor for pointer to - /// blocks. - QualType getBlockDescriptorType() const; - - /// Gets the struct used to keep track of the extended descriptor for - /// pointer to blocks. - QualType getBlockDescriptorExtendedType() const; - - void setcudaConfigureCallDecl(FunctionDecl *FD) { - cudaConfigureCallDecl = FD; - } - FunctionDecl *getcudaConfigureCallDecl() { - return cudaConfigureCallDecl; - } - - /// Returns true iff we need copy/dispose helpers for the given type. - bool BlockRequiresCopying(QualType Ty, const VarDecl *D); - - - /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set - /// to false in this case. If HasByrefExtendedLayout returns true, byref variable - /// has extended lifetime. - bool getByrefLifetime(QualType Ty, - Qualifiers::ObjCLifetime &Lifetime, - bool &HasByrefExtendedLayout) const; - - /// \brief Return the uniqued reference to the type for an lvalue reference - /// to the specified type. - QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true) - const; - - /// \brief Return the uniqued reference to the type for an rvalue reference - /// to the specified type. - QualType getRValueReferenceType(QualType T) const; - - /// \brief Return the uniqued reference to the type for a member pointer to - /// the specified type in the specified class. - /// - /// The class \p Cls is a \c Type because it could be a dependent name. - QualType getMemberPointerType(QualType T, const Type *Cls) const; - - /// \brief Return 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 IndexTypeQuals, - SourceRange Brackets) const; - - /// \brief Return a non-unique reference to the type for a dependently-sized - /// array of the specified element type. - /// - /// FIXME: We will need these to be uniqued, or at least comparable, at some - /// point. - QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, - ArrayType::ArraySizeModifier ASM, - unsigned IndexTypeQuals, - SourceRange Brackets) const; - - /// \brief Return a unique reference to the type for an incomplete array of - /// the specified element type. - QualType getIncompleteArrayType(QualType EltTy, - ArrayType::ArraySizeModifier ASM, - unsigned IndexTypeQuals) const; - - /// \brief 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 IndexTypeQuals) const; - - /// \brief Returns a vla type where known sizes are replaced with [*]. - QualType getVariableArrayDecayedType(QualType Ty) const; - - /// \brief Return the unique reference to a vector type of the specified - /// element type and size. - /// - /// \pre \p VectorType must be a built-in type. - QualType getVectorType(QualType VectorType, unsigned NumElts, - VectorType::VectorKind VecKind) const; - - /// \brief Return the unique reference to an extended vector type - /// of the specified element type and size. - /// - /// \pre \p VectorType must be a built-in type. - QualType getExtVectorType(QualType VectorType, unsigned NumElts) const; - - /// \pre Return a non-unique reference to the type for a dependently-sized - /// vector of the specified element type. - /// - /// FIXME: We will need these to be uniqued, or at least comparable, at some - /// point. - QualType getDependentSizedExtVectorType(QualType VectorType, - Expr *SizeExpr, - SourceLocation AttrLoc) const; - - /// \brief Return a K&R style C function type like 'int()'. - QualType getFunctionNoProtoType(QualType ResultTy, - const FunctionType::ExtInfo &Info) const; - - QualType getFunctionNoProtoType(QualType ResultTy) const { - return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); - } - - /// \brief Return a normal function type with a typed argument list. - QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args, - const FunctionProtoType::ExtProtoInfo &EPI) const; - - /// \brief Return the unique reference to the type for the specified type - /// declaration. - QualType getTypeDeclType(const TypeDecl *Decl, - const TypeDecl *PrevDecl = nullptr) const { - assert(Decl && "Passed null for Decl param"); - if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - - if (PrevDecl) { - assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); - Decl->TypeForDecl = PrevDecl->TypeForDecl; - return QualType(PrevDecl->TypeForDecl, 0); - } - - return getTypeDeclTypeSlow(Decl); - } - - /// \brief Return the unique reference to the type for the specified - /// typedef-name decl. - QualType getTypedefType(const TypedefNameDecl *Decl, - QualType Canon = QualType()) const; - - QualType getRecordType(const RecordDecl *Decl) const; - - QualType getEnumType(const EnumDecl *Decl) const; - - QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; - - QualType getAttributedType(AttributedType::Kind attrKind, - QualType modifiedType, - QualType equivalentType); - - QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, - QualType Replacement) const; - QualType getSubstTemplateTypeParmPackType( - const TemplateTypeParmType *Replaced, - const TemplateArgument &ArgPack); - - QualType - getTemplateTypeParmType(unsigned Depth, unsigned Index, - bool ParameterPack, - TemplateTypeParmDecl *ParmDecl = nullptr) const; - - QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, - QualType Canon = QualType()) const; - - QualType getCanonicalTemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs) const; - - QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgumentListInfo &Args, - QualType Canon = QualType()) const; - - TypeSourceInfo * - getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, - const TemplateArgumentListInfo &Args, - QualType Canon = QualType()) const; - - QualType getParenType(QualType NamedType) const; - - QualType getElaboratedType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - QualType NamedType) const; - QualType getDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon = QualType()) const; - - QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - const TemplateArgumentListInfo &Args) const; - QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args) const; - - QualType getPackExpansionType(QualType Pattern, - Optional<unsigned> NumExpansions); - - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCInterfaceDecl *PrevDecl = nullptr) const; - - /// Legacy interface: cannot provide type arguments or __kindof. - QualType getObjCObjectType(QualType Base, - ObjCProtocolDecl * const *Protocols, - unsigned NumProtocols) const; - - QualType getObjCObjectType(QualType Base, - ArrayRef<QualType> typeArgs, - ArrayRef<ObjCProtocolDecl *> protocols, - bool isKindOf) const; - - bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); - /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in - /// QT's qualified-id protocol list adopt all protocols in IDecl's list - /// of protocols. - bool QIdProtocolsAdoptObjCObjectProtocols(QualType QT, - ObjCInterfaceDecl *IDecl); - - /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType. - QualType getObjCObjectPointerType(QualType OIT) const; - - /// \brief GCC extension. - QualType getTypeOfExprType(Expr *e) const; - QualType getTypeOfType(QualType t) const; - - /// \brief C++11 decltype. - QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; - - /// \brief Unary type transforms - QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType, - UnaryTransformType::UTTKind UKind) const; - - /// \brief C++11 deduced auto type. - QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent) const; - - /// \brief C++11 deduction pattern for 'auto' type. - QualType getAutoDeductType() const; - - /// \brief C++11 deduction pattern for 'auto &&' type. - QualType getAutoRRefDeductType() const; - - /// \brief Return the unique reference to the type for the specified TagDecl - /// (struct/union/class/enum) decl. - QualType getTagDeclType(const TagDecl *Decl) const; - - /// \brief Return the unique type for "size_t" (C99 7.17), defined in - /// <stddef.h>. - /// - /// The sizeof operator requires this (C99 6.5.3.4p4). - CanQualType getSizeType() const; - - /// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in - /// <stdint.h>. - CanQualType getIntMaxType() const; - - /// \brief Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in - /// <stdint.h>. - CanQualType getUIntMaxType() const; - - /// \brief Return the unique wchar_t type available in C++ (and available as - /// __wchar_t as a Microsoft extension). - QualType getWCharType() const { return WCharTy; } - - /// \brief Return the type of wide characters. In C++, this returns the - /// unique wchar_t type. In C99, this returns a type compatible with the type - /// defined in <stddef.h> as defined by the target. - QualType getWideCharType() const { return WideCharTy; } - - /// \brief Return the type of "signed wchar_t". - /// - /// Used when in C++, as a GCC extension. - QualType getSignedWCharType() const; - - /// \brief Return the type of "unsigned wchar_t". - /// - /// Used when in C++, as a GCC extension. - QualType getUnsignedWCharType() const; - - /// \brief In C99, this returns a type compatible with the type - /// defined in <stddef.h> as defined by the target. - QualType getWIntType() const { return WIntTy; } - - /// \brief Return a type compatible with "intptr_t" (C99 7.18.1.4), - /// as defined by the target. - QualType getIntPtrType() const; - - /// \brief Return a type compatible with "uintptr_t" (C99 7.18.1.4), - /// as defined by the target. - QualType getUIntPtrType() const; - - /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in - /// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). - QualType getPointerDiffType() const; - - /// \brief Return the unique type for "pid_t" defined in - /// <sys/types.h>. We need this to compute the correct type for vfork(). - QualType getProcessIDType() const; - - /// \brief Return the C structure type used to represent constant CFStrings. - QualType getCFConstantStringType() const; - - /// \brief Returns the C struct type for objc_super - QualType getObjCSuperType() const; - void setObjCSuperType(QualType ST) { ObjCSuperType = ST; } - - /// Get the structure type used to representation CFStrings, or NULL - /// if it hasn't yet been built. - QualType getRawCFConstantStringType() const { - if (CFConstantStringTypeDecl) - return getTagDeclType(CFConstantStringTypeDecl); - return QualType(); - } - void setCFConstantStringType(QualType T); - - // This setter/getter represents the ObjC type for an NSConstantString. - void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); - QualType getObjCConstantStringInterface() const { - return ObjCConstantStringType; - } - - QualType getObjCNSStringType() const { - return ObjCNSStringType; - } - - void setObjCNSStringType(QualType T) { - ObjCNSStringType = T; - } - - /// \brief Retrieve the type that \c id has been defined to, which may be - /// different from the built-in \c id if \c id has been typedef'd. - QualType getObjCIdRedefinitionType() const { - if (ObjCIdRedefinitionType.isNull()) - return getObjCIdType(); - return ObjCIdRedefinitionType; - } - - /// \brief Set the user-written type that redefines \c id. - void setObjCIdRedefinitionType(QualType RedefType) { - ObjCIdRedefinitionType = RedefType; - } - - /// \brief Retrieve the type that \c Class has been defined to, which may be - /// different from the built-in \c Class if \c Class has been typedef'd. - QualType getObjCClassRedefinitionType() const { - if (ObjCClassRedefinitionType.isNull()) - return getObjCClassType(); - return ObjCClassRedefinitionType; - } - - /// \brief Set the user-written type that redefines 'SEL'. - void setObjCClassRedefinitionType(QualType RedefType) { - ObjCClassRedefinitionType = RedefType; - } - - /// \brief Retrieve the type that 'SEL' has been defined to, which may be - /// different from the built-in 'SEL' if 'SEL' has been typedef'd. - QualType getObjCSelRedefinitionType() const { - if (ObjCSelRedefinitionType.isNull()) - return getObjCSelType(); - return ObjCSelRedefinitionType; - } - - - /// \brief Set the user-written type that redefines 'SEL'. - void setObjCSelRedefinitionType(QualType RedefType) { - ObjCSelRedefinitionType = RedefType; - } - - /// Retrieve the identifier 'NSObject'. - IdentifierInfo *getNSObjectName() { - if (!NSObjectName) { - NSObjectName = &Idents.get("NSObject"); - } - - return NSObjectName; - } - - /// Retrieve the identifier 'NSCopying'. - IdentifierInfo *getNSCopyingName() { - if (!NSCopyingName) { - NSCopyingName = &Idents.get("NSCopying"); - } - - return NSCopyingName; - } - - IdentifierInfo *getMakeIntegerSeqName() const { - if (!MakeIntegerSeqName) - MakeIntegerSeqName = &Idents.get("__make_integer_seq"); - return MakeIntegerSeqName; - } - - /// \brief Retrieve the Objective-C "instancetype" type, if already known; - /// otherwise, returns a NULL type; - QualType getObjCInstanceType() { - return getTypeDeclType(getObjCInstanceTypeDecl()); - } - - /// \brief Retrieve the typedef declaration corresponding to the Objective-C - /// "instancetype" type. - TypedefDecl *getObjCInstanceTypeDecl(); - - /// \brief Set the type for the C FILE type. - void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } - - /// \brief Retrieve the C FILE type. - QualType getFILEType() const { - if (FILEDecl) - return getTypeDeclType(FILEDecl); - return QualType(); - } - - /// \brief Set the type for the C jmp_buf type. - void setjmp_bufDecl(TypeDecl *jmp_bufDecl) { - this->jmp_bufDecl = jmp_bufDecl; - } - - /// \brief Retrieve the C jmp_buf type. - QualType getjmp_bufType() const { - if (jmp_bufDecl) - return getTypeDeclType(jmp_bufDecl); - return QualType(); - } - - /// \brief Set the type for the C sigjmp_buf type. - void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) { - this->sigjmp_bufDecl = sigjmp_bufDecl; - } - - /// \brief Retrieve the C sigjmp_buf type. - QualType getsigjmp_bufType() const { - if (sigjmp_bufDecl) - return getTypeDeclType(sigjmp_bufDecl); - return QualType(); - } - - /// \brief Set the type for the C ucontext_t type. - void setucontext_tDecl(TypeDecl *ucontext_tDecl) { - this->ucontext_tDecl = ucontext_tDecl; - } - - /// \brief Retrieve the C ucontext_t type. - QualType getucontext_tType() const { - if (ucontext_tDecl) - return getTypeDeclType(ucontext_tDecl); - return QualType(); - } - - /// \brief The result type of logical operations, '<', '>', '!=', etc. - QualType getLogicalOperationType() const { - return getLangOpts().CPlusPlus ? BoolTy : IntTy; - } - - /// \brief Emit the Objective-CC type encoding for the given type \p T into - /// \p S. - /// - /// If \p Field is specified then record field names are also encoded. - void getObjCEncodingForType(QualType T, std::string &S, - const FieldDecl *Field=nullptr, - QualType *NotEncodedT=nullptr) const; - - /// \brief Emit the Objective-C property type encoding for the given - /// type \p T into \p S. - void getObjCEncodingForPropertyType(QualType T, std::string &S) const; - - void getLegacyIntegralTypeEncoding(QualType &t) const; - - /// \brief Put the string version of the type qualifiers \p QT into \p S. - void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, - std::string &S) const; - - /// \brief Emit the encoded type for the function \p Decl into \p S. - /// - /// This is in the same format as Objective-C method encodings. - /// - /// \returns true if an error occurred (e.g., because one of the parameter - /// types is incomplete), false otherwise. - bool getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S); - - /// \brief Emit the encoded type for the method declaration \p Decl into - /// \p S. - /// - /// \returns true if an error occurred (e.g., because one of the parameter - /// types is incomplete), false otherwise. - bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S, - bool Extended = false) - const; - - /// \brief Return the encoded type for this block declaration. - std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const; - - /// getObjCEncodingForPropertyDecl - Return the encoded type for - /// this method declaration. If non-NULL, Container must be either - /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should - /// only be NULL when getting encodings for protocol properties. - void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, - const Decl *Container, - std::string &S) const; - - bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, - ObjCProtocolDecl *rProto) const; - - ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl( - const ObjCPropertyDecl *PD, - const Decl *Container) const; - - /// \brief Return the size of type \p T for Objective-C encoding purpose, - /// in characters. - CharUnits getObjCEncodingTypeSize(QualType T) const; - - /// \brief Retrieve the typedef corresponding to the predefined \c id type - /// in Objective-C. - TypedefDecl *getObjCIdDecl() const; - - /// \brief Represents the Objective-CC \c id type. - /// - /// This is set up lazily, by Sema. \c id is always a (typedef for a) - /// pointer type, a pointer to a struct. - QualType getObjCIdType() const { - return getTypeDeclType(getObjCIdDecl()); - } - - /// \brief Retrieve the typedef corresponding to the predefined 'SEL' type - /// in Objective-C. - TypedefDecl *getObjCSelDecl() const; - - /// \brief Retrieve the type that corresponds to the predefined Objective-C - /// 'SEL' type. - QualType getObjCSelType() const { - return getTypeDeclType(getObjCSelDecl()); - } - - /// \brief Retrieve the typedef declaration corresponding to the predefined - /// Objective-C 'Class' type. - TypedefDecl *getObjCClassDecl() const; - - /// \brief Represents the Objective-C \c Class type. - /// - /// This is set up lazily, by Sema. \c Class is always a (typedef for a) - /// pointer type, a pointer to a struct. - QualType getObjCClassType() const { - return getTypeDeclType(getObjCClassDecl()); - } - - /// \brief Retrieve the Objective-C class declaration corresponding to - /// the predefined \c Protocol class. - ObjCInterfaceDecl *getObjCProtocolDecl() const; - - /// \brief Retrieve declaration of 'BOOL' typedef - TypedefDecl *getBOOLDecl() const { - return BOOLDecl; - } - - /// \brief Save declaration of 'BOOL' typedef - void setBOOLDecl(TypedefDecl *TD) { - BOOLDecl = TD; - } - - /// \brief type of 'BOOL' type. - QualType getBOOLType() const { - return getTypeDeclType(getBOOLDecl()); - } - - /// \brief Retrieve the type of the Objective-C \c Protocol class. - QualType getObjCProtoType() const { - return getObjCInterfaceType(getObjCProtocolDecl()); - } - - /// \brief Retrieve the C type declaration corresponding to the predefined - /// \c __builtin_va_list type. - TypedefDecl *getBuiltinVaListDecl() const; - - /// \brief Retrieve the type of the \c __builtin_va_list type. - QualType getBuiltinVaListType() const { - return getTypeDeclType(getBuiltinVaListDecl()); - } - - /// \brief Retrieve the C type declaration corresponding to the predefined - /// \c __va_list_tag type used to help define the \c __builtin_va_list type - /// for some targets. - Decl *getVaListTagDecl() const; - - /// Retrieve the C type declaration corresponding to the predefined - /// \c __builtin_ms_va_list type. - TypedefDecl *getBuiltinMSVaListDecl() const; - - /// Retrieve the type of the \c __builtin_ms_va_list type. - QualType getBuiltinMSVaListType() const { - return getTypeDeclType(getBuiltinMSVaListDecl()); - } - - /// \brief Return a type with additional \c const, \c volatile, or - /// \c restrict qualifiers. - QualType getCVRQualifiedType(QualType T, unsigned CVR) const { - return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); - } - - /// \brief Un-split a SplitQualType. - QualType getQualifiedType(SplitQualType split) const { - return getQualifiedType(split.Ty, split.Quals); - } - - /// \brief Return a type with additional qualifiers. - QualType getQualifiedType(QualType T, Qualifiers Qs) const { - if (!Qs.hasNonFastQualifiers()) - return T.withFastQualifiers(Qs.getFastQualifiers()); - QualifierCollector Qc(Qs); - const Type *Ptr = Qc.strip(T); - return getExtQualType(Ptr, Qc); - } - - /// \brief Return a type with additional qualifiers. - QualType getQualifiedType(const Type *T, Qualifiers Qs) const { - if (!Qs.hasNonFastQualifiers()) - return QualType(T, Qs.getFastQualifiers()); - return getExtQualType(T, Qs); - } - - /// \brief Return a type with the given lifetime qualifier. - /// - /// \pre Neither type.ObjCLifetime() nor \p lifetime may be \c OCL_None. - QualType getLifetimeQualifiedType(QualType type, - Qualifiers::ObjCLifetime lifetime) { - assert(type.getObjCLifetime() == Qualifiers::OCL_None); - assert(lifetime != Qualifiers::OCL_None); - - Qualifiers qs; - qs.addObjCLifetime(lifetime); - return getQualifiedType(type, qs); - } - - /// getUnqualifiedObjCPointerType - Returns version of - /// Objective-C pointer type with lifetime qualifier removed. - QualType getUnqualifiedObjCPointerType(QualType type) const { - if (!type.getTypePtr()->isObjCObjectPointerType() || - !type.getQualifiers().hasObjCLifetime()) - return type; - Qualifiers Qs = type.getQualifiers(); - Qs.removeObjCLifetime(); - return getQualifiedType(type.getUnqualifiedType(), Qs); - } - - DeclarationNameInfo getNameForTemplate(TemplateName Name, - SourceLocation NameLoc) const; - - TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, - UnresolvedSetIterator End) const; - - TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, - bool TemplateKeyword, - TemplateDecl *Template) const; - - TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - const IdentifierInfo *Name) const; - TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) const; - TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, - TemplateName replacement) 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> - GE_Missing_ucontext ///< Missing a type from <ucontext.h> - }; - - /// \brief Return the type for the specified builtin. - /// - /// If \p 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 = nullptr) const; - -private: - CanQualType getFromTargetType(unsigned Type) const; - TypeInfo getTypeInfoImpl(const Type *T) const; - - //===--------------------------------------------------------------------===// - // Type Predicates. - //===--------------------------------------------------------------------===// - -public: - /// \brief Return one of the GCNone, Weak or Strong Objective-C garbage - /// collection attributes. - Qualifiers::GC getObjCGCAttrKind(QualType Ty) const; - - /// \brief Return true if the given vector types are of the same unqualified - /// type or if they are equivalent to the same GCC vector type. - /// - /// \note This ignores whether they are target-specific (AltiVec or Neon) - /// types. - bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); - - /// \brief Return true if this is an \c NSObject object with its \c NSObject - /// attribute set. - static bool isObjCNSObjectType(QualType Ty) { - return Ty->isObjCNSObjectType(); - } - - //===--------------------------------------------------------------------===// - // Type Sizing and Analysis - //===--------------------------------------------------------------------===// - - /// \brief Return the APFloat 'semantics' for the specified scalar floating - /// point type. - const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; - - /// \brief Get the size and alignment of the specified complete type in bits. - TypeInfo getTypeInfo(const Type *T) const; - TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); } - - /// \brief Get default simd alignment of the specified complete type in bits. - unsigned getOpenMPDefaultSimdAlign(QualType T) const; - - /// \brief Return the size of the specified (complete) type \p T, in bits. - uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; } - uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; } - - /// \brief Return the size of the character type, in bits. - uint64_t getCharWidth() const { - return getTypeSize(CharTy); - } - - /// \brief Convert a size in bits to a size in characters. - CharUnits toCharUnitsFromBits(int64_t BitSize) const; - - /// \brief Convert a size in characters to a size in bits. - int64_t toBits(CharUnits CharSize) const; - - /// \brief Return the size of the specified (complete) type \p T, in - /// characters. - CharUnits getTypeSizeInChars(QualType T) const; - CharUnits getTypeSizeInChars(const Type *T) const; - - /// \brief Return the ABI-specified alignment of a (complete) type \p T, in - /// bits. - unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; } - unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; } - - /// \brief Return the ABI-specified alignment of a (complete) type \p T, in - /// characters. - CharUnits getTypeAlignInChars(QualType T) const; - CharUnits getTypeAlignInChars(const Type *T) const; - - // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the - // type is a record, its data size is returned. - std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const; - - std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const; - std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const; - - /// \brief Determine if the alignment the type has was required using an - /// alignment attribute. - bool isAlignmentRequired(const Type *T) const; - bool isAlignmentRequired(QualType T) const; - - /// \brief Return the "preferred" alignment of the specified type \p T 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) const; - - /// \brief Return the default alignment for __attribute__((aligned)) on - /// this target, to be used if no alignment value is specified. - unsigned getTargetDefaultAlignForAttributeAligned(void) const; - - /// \brief Return the alignment in bits that should be given to a - /// global variable with type \p T. - unsigned getAlignOfGlobalVar(QualType T) const; - - /// \brief Return the alignment in characters that should be given to a - /// global variable with type \p T. - CharUnits getAlignOfGlobalVarInChars(QualType T) const; - - /// \brief Return a conservative estimate of the alignment of the specified - /// decl \p D. - /// - /// \pre \p D must not be a bitfield type, as bitfields do not have a valid - /// alignment. - /// - /// If \p ForAlignof, references are treated like their underlying type - /// and large arrays don't get any special treatment. If not \p ForAlignof - /// it computes the value expected by CodeGen: references are treated like - /// pointers and large arrays get extra alignment. - CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const; - - /// \brief Get or compute information about the layout of the specified - /// record (struct/union/class) \p D, which indicates its size and field - /// position information. - const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; - - /// \brief Get or compute information about the layout of the specified - /// Objective-C interface. - const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) - const; - - void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, - bool Simple = false) const; - - /// \brief 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) const; - - /// \brief Get our current best idea for the key function of the - /// given record decl, or NULL if there isn't one. - /// - /// The key function is, according to the Itanium C++ ABI section 5.2.3: - /// ...the first non-pure virtual function that is not inline at the - /// point of class definition. - /// - /// Other ABIs use the same idea. However, the ARM C++ ABI ignores - /// virtual functions that are defined 'inline', which means that - /// the result of this computation can change. - const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD); - - /// \brief Observe that the given method cannot be a key function. - /// Checks the key-function cache for the method's class and clears it - /// if matches the given declaration. - /// - /// This is used in ABIs where out-of-line definitions marked - /// inline are not considered to be key functions. - /// - /// \param method should be the declaration from the class definition - void setNonKeyFunction(const CXXMethodDecl *method); - - /// Loading virtual member pointers using the virtual inheritance model - /// always results in an adjustment using the vbtable even if the index is - /// zero. - /// - /// This is usually OK because the first slot in the vbtable points - /// backwards to the top of the MDC. However, the MDC might be reusing a - /// vbptr from an nv-base. In this case, the first slot in the vbtable - /// points to the start of the nv-base which introduced the vbptr and *not* - /// the MDC. Modify the NonVirtualBaseAdjustment to account for this. - CharUnits getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const; - - /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits. - uint64_t getFieldOffset(const ValueDecl *FD) const; - - bool isNearlyEmpty(const CXXRecordDecl *RD) const; - - VTableContextBase *getVTableContext(); - - MangleContext *createMangleContext(); - - void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, - SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const; - - unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const; - void CollectInheritedProtocols(const Decl *CDecl, - llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); - - //===--------------------------------------------------------------------===// - // Type Operators - //===--------------------------------------------------------------------===// - - /// \brief Return the canonical (structural) type corresponding to the - /// specified potentially non-canonical type \p T. - /// - /// The non-canonical version of a type may have many "decorated" versions of - /// types. Decorators can include typedefs, 'typeof' operators, etc. The - /// returned type is guaranteed to be free of any of these, allowing two - /// canonical types to be compared for exact equality with a simple pointer - /// comparison. - CanQualType getCanonicalType(QualType T) const { - return CanQualType::CreateUnsafe(T.getCanonicalType()); - } - - const Type *getCanonicalType(const Type *T) const { - return T->getCanonicalTypeInternal().getTypePtr(); - } - - /// \brief Return the canonical parameter type 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) const; - - /// \brief Determine whether the given types \p T1 and \p T2 are equivalent. - bool hasSameType(QualType T1, QualType T2) const { - return getCanonicalType(T1) == getCanonicalType(T2); - } - - bool hasSameType(const Type *T1, const Type *T2) const { - return getCanonicalType(T1) == getCanonicalType(T2); - } - - /// \brief Return this type as a completely-unqualified array type, - /// capturing the qualifiers in \p Quals. - /// - /// This will remove the minimal amount of sugaring from the types, similar - /// to the behavior of QualType::getUnqualifiedType(). - /// - /// \param T is the qualified type, which may be an ArrayType - /// - /// \param Quals will receive the full set of qualifiers that were - /// applied to the array. - /// - /// \returns if this is an array type, the completely unqualified array type - /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals); - - /// \brief Determine whether the given types are equivalent after - /// cvr-qualifiers have been removed. - bool hasSameUnqualifiedType(QualType T1, QualType T2) const { - return getCanonicalType(T1).getTypePtr() == - getCanonicalType(T2).getTypePtr(); - } - - bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT, - bool IsParam) const { - auto SubTnullability = SubT->getNullability(*this); - auto SuperTnullability = SuperT->getNullability(*this); - if (SubTnullability.hasValue() == SuperTnullability.hasValue()) { - // Neither has nullability; return true - if (!SubTnullability) - return true; - // Both have nullability qualifier. - if (*SubTnullability == *SuperTnullability || - *SubTnullability == NullabilityKind::Unspecified || - *SuperTnullability == NullabilityKind::Unspecified) - return true; - - if (IsParam) { - // Ok for the superclass method parameter to be "nonnull" and the subclass - // method parameter to be "nullable" - return (*SuperTnullability == NullabilityKind::NonNull && - *SubTnullability == NullabilityKind::Nullable); - } - else { - // For the return type, it's okay for the superclass method to specify - // "nullable" and the subclass method specify "nonnull" - return (*SuperTnullability == NullabilityKind::Nullable && - *SubTnullability == NullabilityKind::NonNull); - } - } - return true; - } - - bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, - const ObjCMethodDecl *MethodImp); - - bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); - - /// \brief Retrieves the "canonical" nested name specifier for a - /// given nested name specifier. - /// - /// The canonical nested name specifier is a nested name specifier - /// that uniquely identifies a type or namespace within the type - /// system. For example, given: - /// - /// \code - /// namespace N { - /// struct S { - /// template<typename T> struct X { typename T* type; }; - /// }; - /// } - /// - /// template<typename T> struct Y { - /// typename N::S::X<T>::type member; - /// }; - /// \endcode - /// - /// Here, the nested-name-specifier for N::S::X<T>:: will be - /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined - /// 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) const; - - /// \brief Retrieves the default calling convention for the current target. - CallingConv getDefaultCallingConvention(bool isVariadic, - bool IsCXXMethod) const; - - /// \brief Retrieves the "canonical" template name that refers to a - /// given template. - /// - /// The canonical template name is the simplest expression that can - /// be used to refer to a given template. For most templates, this - /// expression is just the template declaration itself. For example, - /// the template std::vector can be referred to via a variety of - /// names---std::vector, \::std::vector, vector (if vector is in - /// scope), etc.---but all of these names map down to the same - /// TemplateDecl, which is used to form the canonical template name. - /// - /// Dependent template names are more interesting. Here, the - /// template name could be something like T::template apply or - /// std::allocator<T>::template rebind, where the nested name - /// specifier itself is dependent. In this case, the canonical - /// 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) const; - - /// \brief Determine whether the given template names refer to the same - /// template. - bool hasSameTemplateName(TemplateName X, TemplateName Y); - - /// \brief Retrieve the "canonical" template argument. - /// - /// The canonical template argument is the simplest template argument - /// (which may be a type, value, expression, or declaration) that - /// expresses the value of the argument. - TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) - 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; - const ConstantArrayType *getAsConstantArrayType(QualType T) const { - return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T)); - } - const VariableArrayType *getAsVariableArrayType(QualType T) const { - return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T)); - } - const IncompleteArrayType *getAsIncompleteArrayType(QualType T) const { - return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T)); - } - const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) - const { - return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T)); - } - - /// \brief Return the innermost element type of an array type. - /// - /// For example, will return "int" for int[m][n] - QualType getBaseElementType(const ArrayType *VAT) const; - - /// \brief Return the innermost element type of a type (which needn't - /// actually be an array type). - QualType getBaseElementType(QualType QT) const; - - /// \brief Return number of constant array elements. - uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; - - /// \brief Perform adjustment on the parameter type of a function. - /// - /// This routine adjusts the given parameter type @p T to the actual - /// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], - /// C++ [dcl.fct]p3). The adjusted parameter type is returned. - QualType getAdjustedParameterType(QualType T) const; - - /// \brief Retrieve the parameter type as adjusted for use in the signature - /// of a function, decaying array and function types and removing top-level - /// cv-qualifiers. - QualType getSignatureParameterType(QualType T) const; - - QualType getExceptionObjectType(QualType T) const; - - /// \brief Return the properly qualified result of decaying the specified - /// array type to a pointer. - /// - /// This operation is non-trivial when handling typedefs etc. The canonical - /// type of \p T must be an array type, 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) const; - - /// \brief Return the type that \p PromotableType will promote to: C99 - /// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type. - QualType getPromotedIntegerType(QualType PromotableType) const; - - /// \brief Recurses in pointer/array types until it finds an Objective-C - /// retainable type and returns its ownership. - Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) 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) const; - - /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1. - /// - /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If - /// \p LHS < \p RHS, return -1. - int getIntegerTypeOrder(QualType LHS, QualType RHS) const; - - /// \brief Compare the rank of the two specified floating point types, - /// ignoring the domain of the type (i.e. 'double' == '_Complex double'). - /// - /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If - /// \p LHS < \p RHS, return -1. - int getFloatingTypeOrder(QualType LHS, QualType RHS) const; - - /// \brief Return a real floating point or a complex type (based on - /// \p typeDomain/\p typeSize). - /// - /// \param typeDomain a real floating point or complex type. - /// \param typeSize a real floating point or complex type. - QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, - QualType typeDomain) const; - - unsigned getTargetAddressSpace(QualType T) const { - return getTargetAddressSpace(T.getQualifiers()); - } - - unsigned getTargetAddressSpace(Qualifiers Q) const { - return getTargetAddressSpace(Q.getAddressSpace()); - } - - unsigned getTargetAddressSpace(unsigned AS) const { - if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) - return AS; - else - return (*AddrSpaceMap)[AS - LangAS::Offset]; - } - - bool addressSpaceMapManglingFor(unsigned AS) const { - return AddrSpaceMapMangling || - AS < LangAS::Offset || - AS >= LangAS::Offset + LangAS::Count; - } - -private: - // Helper for integer ordering - unsigned getIntegerRank(const Type *T) const; - -public: - - //===--------------------------------------------------------------------===// - // Type Compatibility Predicates - //===--------------------------------------------------------------------===// - - /// Compatibility predicates used to check assignment expressions. - bool typesAreCompatible(QualType T1, QualType T2, - bool CompareUnqualified = false); // C99 6.2.7p1 - - bool propertyTypesAreCompatible(QualType, QualType); - bool typesAreBlockPointerCompatible(QualType, QualType); - - bool isObjCIdType(QualType T) const { - return T == getObjCIdType(); - } - bool isObjCClassType(QualType T) const { - return T == getObjCClassType(); - } - bool isObjCSelType(QualType T) const { - return T == getObjCSelType(); - } - bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, - bool ForCompare); - - bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS); - - // Check the safety of assignment from LHS to RHS - bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT); - bool canAssignObjCInterfaces(const ObjCObjectType *LHS, - const ObjCObjectType *RHS); - bool canAssignObjCInterfacesInBlockPointer( - const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT, - bool BlockReturnType); - bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); - QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT); - bool canBindObjCObjectType(QualType To, QualType From); - - // Functions for calculating composite types - QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false, bool BlockReturnType = false); - QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false); - QualType mergeFunctionParameterTypes(QualType, QualType, - bool OfBlockPointer = false, - bool Unqualified = false); - QualType mergeTransparentUnionType(QualType, QualType, - bool OfBlockPointer=false, - bool Unqualified = false); - - QualType mergeObjCGCQualifiers(QualType, QualType); - - bool FunctionTypesMatchOnNSConsumedAttrs( - const FunctionProtoType *FromFunctionType, - const FunctionProtoType *ToFunctionType); - - void ResetObjCLayout(const ObjCContainerDecl *CD); - - //===--------------------------------------------------------------------===// - // Integer Predicates - //===--------------------------------------------------------------------===// - - // 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) 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 - // corresponding unsigned integer type. - QualType getCorrespondingUnsignedType(QualType T) const; - - //===--------------------------------------------------------------------===// - // Integer Values - //===--------------------------------------------------------------------===// - - /// \brief Make an APSInt of the appropriate width and signedness for the - /// given \p Value and integer \p Type. - llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { - llvm::APSInt Res(getIntWidth(Type), - !Type->isSignedIntegerOrEnumerationType()); - Res = Value; - return Res; - } - - bool isSentinelNullExpr(const Expr *E); - - /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if - /// none exists. - ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D); - /// \brief Get the implementation of the ObjCCategoryDecl \p D, or NULL if - /// none exists. - ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); - - /// \brief Return true if there is at least one \@implementation in the 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 Get the duplicate declaration of a ObjCMethod in the same - /// interface, or null if none exists. - const ObjCMethodDecl * - getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const; - - void setObjCMethodRedeclaration(const ObjCMethodDecl *MD, - const ObjCMethodDecl *Redecl); - - /// \brief Returns the Objective-C interface that \p ND belongs to if it is - /// an Objective-C method/property/ivar etc. that is part of an interface, - /// otherwise returns null. - const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const; - - /// \brief Set the copy inialization expression of a block var decl. - void setBlockVarCopyInits(VarDecl*VD, Expr* Init); - /// \brief Get the copy initialization expression of the VarDecl \p VD, or - /// NULL if none exists. - Expr *getBlockVarCopyInits(const VarDecl* VD); - - /// \brief Allocate an uninitialized TypeSourceInfo. - /// - /// The caller should initialize the memory held by TypeSourceInfo using - /// the TypeLoc wrappers. - /// - /// \param T the type that will be the basis for type source info. This type - /// should refer to how the declarator was written in source code, not to - /// what type semantic analysis resolved the declarator to. - /// - /// \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) 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()) const; - - /// \brief Add a deallocation callback that will be invoked when the - /// ASTContext is destroyed. - /// - /// \param Callback A callback function that will be invoked on destruction. - /// - /// \param Data Pointer data that will be provided to the callback function - /// when it is called. - void AddDeallocation(void (*Callback)(void*), void *Data); - - GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; - GVALinkage GetGVALinkageForVariable(const VarDecl *VD); - - /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH - /// lazily, only when used; this is only relevant for function or file scoped - /// var definitions. - /// - /// \returns true if the function/var must be CodeGen'ed/deserialized even if - /// it is not used. - bool DeclMustBeEmitted(const Decl *D); - - const CXXConstructorDecl * - getCopyConstructorForExceptionObject(CXXRecordDecl *RD); - - void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, - CXXConstructorDecl *CD); - - void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE); - - Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx); - - void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND); - - TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD); - - void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD); - - DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD); - - void setManglingNumber(const NamedDecl *ND, unsigned Number); - unsigned getManglingNumber(const NamedDecl *ND) const; - - void setStaticLocalNumber(const VarDecl *VD, unsigned Number); - unsigned getStaticLocalNumber(const VarDecl *VD) const; - - /// \brief Retrieve the context for computing mangling numbers in the given - /// DeclContext. - MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); - - MangleNumberingContext *createMangleNumberingContext() const; - - /// \brief Used by ParmVarDecl to store on the side the - /// index of the parameter when it exceeds the size of the normal bitfield. - void setParameterIndex(const ParmVarDecl *D, unsigned index); - - /// \brief Used by ParmVarDecl to retrieve on the side the - /// index of the parameter when it exceeds the size of the normal bitfield. - unsigned getParameterIndex(const ParmVarDecl *D) const; - - /// \brief Get the storage for the constant value of a materialized temporary - /// of static storage duration. - APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, - bool MayCreate); - - //===--------------------------------------------------------------------===// - // Statistics - //===--------------------------------------------------------------------===// - - /// \brief The number of implicitly-declared default constructors. - static unsigned NumImplicitDefaultConstructors; - - /// \brief The number of implicitly-declared default constructors for - /// which declarations were built. - static unsigned NumImplicitDefaultConstructorsDeclared; - - /// \brief The number of implicitly-declared copy constructors. - static unsigned NumImplicitCopyConstructors; - - /// \brief The number of implicitly-declared copy constructors for - /// which declarations were built. - static unsigned NumImplicitCopyConstructorsDeclared; - - /// \brief The number of implicitly-declared move constructors. - static unsigned NumImplicitMoveConstructors; - - /// \brief The number of implicitly-declared move constructors for - /// which declarations were built. - static unsigned NumImplicitMoveConstructorsDeclared; - - /// \brief The number of implicitly-declared copy assignment operators. - static unsigned NumImplicitCopyAssignmentOperators; - - /// \brief The number of implicitly-declared copy assignment operators for - /// which declarations were built. - static unsigned NumImplicitCopyAssignmentOperatorsDeclared; - - /// \brief The number of implicitly-declared move assignment operators. - static unsigned NumImplicitMoveAssignmentOperators; - - /// \brief The number of implicitly-declared move assignment operators for - /// which declarations were built. - static unsigned NumImplicitMoveAssignmentOperatorsDeclared; - - /// \brief The number of implicitly-declared destructors. - static unsigned NumImplicitDestructors; - - /// \brief The number of implicitly-declared destructors for which - /// declarations were built. - static unsigned NumImplicitDestructorsDeclared; - -private: - ASTContext(const ASTContext &) = delete; - void operator=(const ASTContext &) = delete; - -public: - /// \brief Initialize built-in types. - /// - /// This routine may only be invoked once for a given ASTContext object. - /// It is normally invoked after ASTContext construction. - /// - /// \param Target The target - void InitBuiltinTypes(const TargetInfo &Target, - const TargetInfo *AuxTarget = nullptr); - -private: - void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); - - // Return the Objective-C type encoding for a given type. - void getObjCEncodingForTypeImpl(QualType t, std::string &S, - bool ExpandPointedToStructures, - bool ExpandStructures, - const FieldDecl *Field, - bool OutermostType = false, - bool EncodingProperty = false, - bool StructField = false, - bool EncodeBlockParameters = false, - bool EncodeClassNames = false, - bool EncodePointerToObjCTypedef = false, - QualType *NotEncodedT=nullptr) const; - - // Adds the encoding of the structure's members. - void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, - const FieldDecl *Field, - bool includeVBases = true, - QualType *NotEncodedT=nullptr) const; -public: - // Adds the encoding of a method parameter or return type. - void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, - QualType T, std::string& S, - bool Extended) const; - - /// \brief Returns true if this is an inline-initialized static data member - /// which is treated as a definition for MSVC compatibility. - bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; - -private: - const ASTRecordLayout & - getObjCLayout(const ObjCInterfaceDecl *D, - const ObjCImplementationDecl *Impl) const; - - /// \brief A set of deallocations that should be performed when the - /// ASTContext is destroyed. - // FIXME: We really should have a better mechanism in the ASTContext to - // manage running destructors for types which do variable sized allocation - // within the AST. In some places we thread the AST bump pointer allocator - // into the datastructures which avoids this mess during deallocation but is - // wasteful of memory, and here we require a lot of error prone book keeping - // in order to track and run destructors while we're tearing things down. - typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16> - DeallocationFunctionsAndArguments; - DeallocationFunctionsAndArguments Deallocations; - - // FIXME: This currently contains the set of StoredDeclMaps used - // by DeclContext objects. This probably should not be in ASTContext, - // but we include it here so that ASTContext can quickly deallocate them. - llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; - - friend class DeclContext; - friend class DeclarationNameTable; - void ReleaseDeclContextMaps(); - void ReleaseParentMapEntries(); - - std::unique_ptr<ParentMapPointers> PointerParents; - std::unique_ptr<ParentMapOtherNodes> OtherParents; - - std::unique_ptr<VTableContextBase> VTContext; - -public: - enum PragmaSectionFlag : unsigned { - PSF_None = 0, - PSF_Read = 0x1, - PSF_Write = 0x2, - PSF_Execute = 0x4, - PSF_Implicit = 0x8, - PSF_Invalid = 0x80000000U, - }; - - struct SectionInfo { - DeclaratorDecl *Decl; - SourceLocation PragmaSectionLocation; - int SectionFlags; - SectionInfo() {} - SectionInfo(DeclaratorDecl *Decl, - SourceLocation PragmaSectionLocation, - int SectionFlags) - : Decl(Decl), - PragmaSectionLocation(PragmaSectionLocation), - SectionFlags(SectionFlags) {} - }; - - llvm::StringMap<SectionInfo> SectionInfos; -}; - -/// \brief Utility function for constructing a nullary selector. -static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) { - IdentifierInfo* II = &Ctx.Idents.get(name); - return Ctx.Selectors.getSelector(0, &II); -} - -/// \brief Utility function for constructing an unary selector. -static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { - IdentifierInfo* II = &Ctx.Idents.get(name); - return Ctx.Selectors.getSelector(1, &II); -} - -} // end namespace clang - -// operator new and delete aren't allowed inside namespaces. - -/// @brief Placement new for using the ASTContext's allocator. -/// -/// This placement form of operator new uses the ASTContext's allocator for -/// obtaining memory. -/// -/// IMPORTANT: These are also declared in clang/AST/AttrIterator.h! Any changes -/// here need to also be made there. -/// -/// We intentionally avoid using a nothrow specification here so that the calls -/// to this operator will not perform a null check on the result -- the -/// underlying allocator never returns null pointers. -/// -/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): -/// @code -/// // Default alignment (8) -/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); -/// // Specific alignment -/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); -/// @endcode -/// Memory allocated through this placement new operator does not need to be -/// explicitly freed, as ASTContext will free all of this memory when it gets -/// destroyed. Please note that you cannot use delete on the pointer. -/// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The ASTContext that provides the allocator. -/// @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, const clang::ASTContext &C, - size_t Alignment) { - return C.Allocate(Bytes, Alignment); -} -/// @brief Placement delete companion to the new above. -/// -/// This operator is just a companion to the new above. There is no way of -/// 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, const clang::ASTContext &C, size_t) { - C.Deallocate(Ptr); -} - -/// This placement form of operator new[] uses the ASTContext's allocator for -/// obtaining memory. -/// -/// We intentionally avoid using a nothrow specification here so that the calls -/// to this operator will not perform a null check on the result -- the -/// underlying allocator never returns null pointers. -/// -/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): -/// @code -/// // Default alignment (8) -/// char *data = new (Context) char[10]; -/// // Specific alignment -/// char *data = new (Context, 4) char[10]; -/// @endcode -/// Memory allocated through this placement new[] operator does not need to be -/// explicitly freed, as ASTContext will free all of this memory when it gets -/// destroyed. Please note that you cannot use delete on the pointer. -/// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The ASTContext that provides the allocator. -/// @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, const clang::ASTContext& C, - size_t Alignment = 8) { - return C.Allocate(Bytes, Alignment); -} - -/// @brief Placement delete[] companion to the new[] above. -/// -/// This operator is just a companion to the new[] above. There is no way of -/// 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, const clang::ASTContext &C, size_t) { - C.Deallocate(Ptr); -} - -/// \brief Create the representation of a LazyGenerationalUpdatePtr. -template <typename Owner, typename T, - void (clang::ExternalASTSource::*Update)(Owner)> -typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType - clang::LazyGenerationalUpdatePtr<Owner, T, Update>::makeValue( - const clang::ASTContext &Ctx, T Value) { - // Note, this is implemented here so that ExternalASTSource.h doesn't need to - // include ASTContext.h. We explicitly instantiate it for all relevant types - // in ASTContext.cpp. - if (auto *Source = Ctx.getExternalSource()) - return new (Ctx) LazyData(Source, Value); - return Value; -} - -#endif diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h deleted file mode 100644 index 27c85e6..0000000 --- a/include/clang/AST/ASTDiagnostic.h +++ /dev/null @@ -1,47 +0,0 @@ -//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H -#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H - -#include "clang/Basic/Diagnostic.h" - -namespace clang { - namespace diag { - enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, -#define ASTSTART -#include "clang/Basic/DiagnosticASTKinds.inc" -#undef DIAG - NUM_BUILTIN_AST_DIAGNOSTICS - }; - } // end namespace diag - - /// \brief DiagnosticsEngine argument formatting function for diagnostics that - /// involve AST nodes. - /// - /// This function formats diagnostic arguments for various AST nodes, - /// including types, declaration names, nested name specifiers, and - /// declaration contexts, into strings that can be printed as part of - /// diagnostics. It is meant to be used as the argument to - /// \c DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c - /// ASTContext pointer. - void FormatASTNodeDiagnosticArgument( - DiagnosticsEngine::ArgumentKind Kind, - intptr_t Val, - StringRef Modifier, - StringRef Argument, - ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, - SmallVectorImpl<char> &Output, - void *Cookie, - ArrayRef<intptr_t> QualTypeVals); -} // end namespace clang - -#endif diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h deleted file mode 100644 index 003d489..0000000 --- a/include/clang/AST/ASTFwd.h +++ /dev/null @@ -1,33 +0,0 @@ -//===--- ASTFwd.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------===// -/// -/// \file -/// \brief Forward declaration of all AST node types. -/// -//===-------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTFWD_H -#define LLVM_CLANG_AST_ASTFWD_H - -namespace clang { - -class Decl; -#define DECL(DERIVED, BASE) class DERIVED##Decl; -#include "clang/AST/DeclNodes.inc" -class Stmt; -#define STMT(DERIVED, BASE) class DERIVED; -#include "clang/AST/StmtNodes.inc" -class Type; -#define TYPE(DERIVED, BASE) class DERIVED##Type; -#include "clang/AST/TypeNodes.def" -class CXXCtorInitializer; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h deleted file mode 100644 index ee48955..0000000 --- a/include/clang/AST/ASTImporter.h +++ /dev/null @@ -1,295 +0,0 @@ -//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- 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 ASTImporter class which imports AST nodes from one -// context into another context. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_ASTIMPORTER_H -#define LLVM_CLANG_AST_ASTIMPORTER_H - -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" - -namespace clang { - class ASTContext; - class Decl; - class DeclContext; - class DiagnosticsEngine; - class Expr; - class FileManager; - class IdentifierInfo; - class NestedNameSpecifier; - class Stmt; - class TypeSourceInfo; - - /// \brief Imports selected nodes from one AST context into another context, - /// merging AST nodes where appropriate. - class ASTImporter { - public: - typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet; - - private: - /// \brief The contexts we're importing to and from. - ASTContext &ToContext, &FromContext; - - /// \brief The file managers we're importing to and from. - FileManager &ToFileManager, &FromFileManager; - - /// \brief Whether to perform a minimal import. - bool Minimal; - - /// \brief Whether the last diagnostic came from the "from" context. - bool LastDiagFromFrom; - - /// \brief Mapping from the already-imported types in the "from" context - /// to the corresponding types in the "to" context. - 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. - llvm::DenseMap<Decl *, Decl *> ImportedDecls; - - /// \brief Mapping from the already-imported statements in the "from" - /// context to the corresponding statements in the "to" context. - llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; - - /// \brief Mapping from the already-imported FileIDs in the "from" source - /// manager to the corresponding FileIDs in the "to" source manager. - llvm::DenseMap<FileID, FileID> ImportedFileIDs; - - /// \brief Imported, anonymous tag declarations that are missing their - /// corresponding typedefs. - SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs; - - /// \brief Declaration (from, to) pairs that are known not to be equivalent - /// (which we have already complained about). - NonEquivalentDeclSet NonEquivalentDecls; - - public: - /// \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. - /// - /// \returns the equivalent type in the "to" context, or a NULL type if - /// an error occurred. - QualType Import(QualType FromT); - - /// \brief Import the given type source information from the - /// "from" context into the "to" context. - /// - /// \returns the equivalent type source information in the "to" - /// context, or NULL if an error occurred. - TypeSourceInfo *Import(TypeSourceInfo *FromTSI); - - /// \brief Import the given declaration from the "from" context into the - /// "to" context. - /// - /// \returns the equivalent declaration in the "to" context, or a NULL type - /// if an error occurred. - Decl *Import(Decl *FromD); - - /// \brief Return the copy of the given declaration in the "to" context if - /// it has already been imported from the "from" context. Otherwise return - /// NULL. - Decl *GetAlreadyImportedOrNull(Decl *FromD); - - /// \brief Import the given declaration context from the "from" - /// AST context into the "to" AST context. - /// - /// \returns the equivalent declaration context in the "to" - /// context, or a NULL type if an error occurred. - DeclContext *ImportContext(DeclContext *FromDC); - - /// \brief Import the given expression from the "from" context into the - /// "to" context. - /// - /// \returns the equivalent expression in the "to" context, or NULL if - /// an error occurred. - Expr *Import(Expr *FromE); - - /// \brief Import the given statement from the "from" context into the - /// "to" context. - /// - /// \returns the equivalent statement in the "to" context, or NULL if - /// an error occurred. - Stmt *Import(Stmt *FromS); - - /// \brief Import the given nested-name-specifier from the "from" - /// context into the "to" context. - /// - /// \returns the equivalent nested-name-specifier in the "to" - /// context, or NULL if an error occurred. - NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); - - /// \brief Import the given nested-name-specifier from the "from" - /// context into the "to" context. - /// - /// \returns the equivalent nested-name-specifier in the "to" - /// context. - NestedNameSpecifierLoc Import(NestedNameSpecifierLoc 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. - /// - /// \returns the equivalent source location in the "to" context, or an - /// invalid source location if an error occurred. - SourceLocation Import(SourceLocation FromLoc); - - /// \brief Import the given source range from the "from" context into - /// the "to" context. - /// - /// \returns the equivalent source range in the "to" context, or an - /// invalid source location if an error occurred. - SourceRange Import(SourceRange FromRange); - - /// \brief Import the given declaration name from the "from" - /// context into the "to" context. - /// - /// \returns the equivalent declaration name in the "to" context, - /// or an empty declaration name if an error occurred. - DeclarationName Import(DeclarationName FromName); - - /// \brief Import the given identifier from the "from" context - /// into the "to" context. - /// - /// \returns the equivalent identifier in the "to" context. - IdentifierInfo *Import(const IdentifierInfo *FromId); - - /// \brief Import the given Objective-C selector from the "from" - /// context into the "to" context. - /// - /// \returns the equivalent selector in the "to" context. - Selector Import(Selector FromSel); - - /// \brief Import the given file ID from the "from" context into the - /// "to" context. - /// - /// \returns the equivalent file ID in the source manager of the "to" - /// 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. - /// - /// This routine is invoked whenever there is a name conflict while - /// importing a declaration. The returned name will become the name of the - /// imported declaration. By default, the returned name is the same as the - /// original name, leaving the conflict unresolve such that name lookup - /// for this name is likely to find an ambiguity later. - /// - /// Subclasses may override this routine to resolve the conflict, e.g., by - /// renaming the declaration being imported. - /// - /// \param Name the name of the declaration being imported, which conflicts - /// with other declarations. - /// - /// \param DC the declaration context (in the "to" AST context) in which - /// the name is being imported. - /// - /// \param IDNS the identifier namespace in which the name will be found. - /// - /// \param Decls the set of declarations with the same name as the - /// declaration being imported. - /// - /// \param NumDecls the number of conflicting declarations in \p Decls. - /// - /// \returns the name that the newly-imported declaration should have. - virtual DeclarationName HandleNameConflict(DeclarationName Name, - DeclContext *DC, - unsigned IDNS, - NamedDecl **Decls, - unsigned NumDecls); - - /// \brief Retrieve the context that AST nodes are being imported into. - ASTContext &getToContext() const { return ToContext; } - - /// \brief Retrieve the context that AST nodes are being imported from. - ASTContext &getFromContext() const { return FromContext; } - - /// \brief Retrieve the file manager that AST nodes are being imported into. - FileManager &getToFileManager() const { return ToFileManager; } - - /// \brief Retrieve the file manager that AST nodes are being imported from. - FileManager &getFromFileManager() const { return FromFileManager; } - - /// \brief Report a diagnostic in the "to" context. - DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); - - /// \brief Report a diagnostic in the "from" context. - DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); - - /// \brief Return the set of declarations that we know are not equivalent. - NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } - - /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. - /// Mark the Decl as complete, filling it in as much as possible. - /// - /// \param D A declaration in the "to" context. - virtual void CompleteDecl(Decl* D); - - /// \brief Note that we have imported the "from" declaration by mapping it - /// to the (potentially-newly-created) "to" declaration. - /// - /// 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 Called by StructuralEquivalenceContext. If a RecordDecl is - /// being compared to another RecordDecl as part of import, completing the - /// other RecordDecl may trigger importation of the first RecordDecl. This - /// happens especially for anonymous structs. If the original of the second - /// RecordDecl can be found, we can complete it without the need for - /// importation, eliminating this loop. - virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } - - /// \brief Determine whether the given types are structurally - /// equivalent. - bool IsStructurallyEquivalent(QualType From, QualType To, - bool Complain = true); - }; -} - -#endif // LLVM_CLANG_AST_ASTIMPORTER_H diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h deleted file mode 100644 index 69df2d8..0000000 --- a/include/clang/AST/ASTLambda.h +++ /dev/null @@ -1,80 +0,0 @@ -//===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file provides some common utility functions for processing -/// Lambda related AST Constructs. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTLAMBDA_H -#define LLVM_CLANG_AST_ASTLAMBDA_H - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" - -namespace clang { -inline StringRef getLambdaStaticInvokerName() { - return "__invoke"; -} -// This function returns true if M is a specialization, a template, -// or a non-generic lambda call operator. -inline bool isLambdaCallOperator(const CXXMethodDecl *MD) { - const CXXRecordDecl *LambdaClass = MD->getParent(); - if (!LambdaClass || !LambdaClass->isLambda()) return false; - return MD->getOverloadedOperator() == OO_Call; -} - -inline bool isLambdaCallOperator(const DeclContext *DC) { - if (!DC || !isa<CXXMethodDecl>(DC)) return false; - return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); -} - -inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { - if (!MD) return false; - const CXXRecordDecl *LambdaClass = MD->getParent(); - if (LambdaClass && LambdaClass->isGenericLambda()) - return isLambdaCallOperator(MD) && - MD->isFunctionTemplateSpecialization(); - return false; -} - -inline bool isLambdaConversionOperator(CXXConversionDecl *C) { - return C ? C->getParent()->isLambda() : false; -} - -inline bool isLambdaConversionOperator(Decl *D) { - if (!D) return false; - if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) - return isLambdaConversionOperator(Conv); - if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D)) - if (CXXConversionDecl *Conv = - dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl())) - return isLambdaConversionOperator(Conv); - return false; -} - -inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { - return isGenericLambdaCallOperatorSpecialization( - dyn_cast<CXXMethodDecl>(DC)); -} - - -// This returns the parent DeclContext ensuring that the correct -// parent DeclContext is returned for Lambdas -inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { - if (isLambdaCallOperator(DC)) - return DC->getParent()->getParent(); - else - return DC->getParent(); -} - -} // clang - -#endif diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h deleted file mode 100644 index 3ff392d..0000000 --- a/include/clang/AST/ASTMutationListener.h +++ /dev/null @@ -1,127 +0,0 @@ -//===--- 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 Attr; - class ClassTemplateDecl; - class ClassTemplateSpecializationDecl; - class CXXDestructorDecl; - class CXXRecordDecl; - class Decl; - class DeclContext; - class FunctionDecl; - class FunctionTemplateDecl; - class Module; - class NamedDecl; - class ObjCCategoryDecl; - class ObjCContainerDecl; - class ObjCInterfaceDecl; - class ObjCPropertyDecl; - class QualType; - class RecordDecl; - class TagDecl; - class VarDecl; - class VarTemplateDecl; - class VarTemplateSpecializationDecl; - -/// \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) {} - - /// \brief A template specialization (or partial one) was added to the - /// template declaration. - virtual void - AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, - const VarTemplateSpecializationDecl *D) {} - - /// \brief A template specialization (or partial one) was added to the - /// template declaration. - virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, - const FunctionDecl *D) {} - - /// \brief A function's exception specification has been evaluated or - /// instantiated. - virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {} - - /// \brief A function's return type has been deduced. - virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); - - /// \brief A virtual destructor's operator delete has been resolved. - virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) {} - - /// \brief An implicit member got a definition. - virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} - - /// \brief A static data member was implicitly instantiated. - virtual void StaticDataMemberInstantiated(const VarDecl *D) {} - - /// \brief A function template's definition was instantiated. - virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} - - /// \brief A new objc category class was added for an interface. - virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, - const ObjCInterfaceDecl *IFD) {} - - /// \brief A declaration is marked used which was not previously marked used. - /// - /// \param D the declaration marked used - virtual void DeclarationMarkedUsed(const Decl *D) {} - - /// \brief A declaration is marked as OpenMP threadprivate which was not - /// previously marked as threadprivate. - /// - /// \param D the declaration marked OpenMP threadprivate. - virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {} - - /// \brief A definition has been made visible by being redefined locally. - /// - /// \param D The definition that was previously not visible. - /// \param M The containing module in which the definition was made visible, - /// if any. - virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {} - - /// \brief An attribute was added to a RecordDecl - /// - /// \param Attr The attribute that was added to the Record - /// - /// \param Record The RecordDecl that got a new attribute - virtual void AddedAttributeToRecord(const Attr *Attr, - const RecordDecl *Record) {} - - // NOTE: If new methods are added they should also be added to - // MultiplexASTMutationListener. -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h deleted file mode 100644 index dcaac80..0000000 --- a/include/clang/AST/ASTTypeTraits.h +++ /dev/null @@ -1,509 +0,0 @@ -//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Provides a dynamic type identifier and a dynamically typed node container -// that can be used to store an AST base node at runtime in the same storage in -// a type safe way. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H -#define LLVM_CLANG_AST_ASTTYPETRAITS_H - -#include "clang/AST/ASTFwd.h" -#include "clang/AST/Decl.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TypeLoc.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/Support/AlignOf.h" - -namespace llvm { - -class raw_ostream; - -} - -namespace clang { - -struct PrintingPolicy; - -namespace ast_type_traits { - -/// \brief Kind identifier. -/// -/// It can be constructed from any node kind and allows for runtime type -/// hierarchy checks. -/// Use getFromNodeKind<T>() to construct them. -class ASTNodeKind { -public: - /// \brief Empty identifier. It matches nothing. - ASTNodeKind() : KindId(NKI_None) {} - - /// \brief Construct an identifier for T. - template <class T> - static ASTNodeKind getFromNodeKind() { - return ASTNodeKind(KindToKindId<T>::Id); - } - - /// \{ - /// \brief Construct an identifier for the dynamic type of the node - static ASTNodeKind getFromNode(const Decl &D); - static ASTNodeKind getFromNode(const Stmt &S); - static ASTNodeKind getFromNode(const Type &T); - /// \} - - /// \brief Returns \c true if \c this and \c Other represent the same kind. - bool isSame(ASTNodeKind Other) const; - - /// \brief Returns \c true only for the default \c ASTNodeKind() - bool isNone() const { return KindId == NKI_None; } - - /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. - /// \param Distance If non-null, used to return the distance between \c this - /// and \c Other in the class hierarchy. - bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; - - /// \brief String representation of the kind. - StringRef asStringRef() const; - - /// \brief Strict weak ordering for ASTNodeKind. - bool operator<(const ASTNodeKind &Other) const { - return KindId < Other.KindId; - } - - /// \brief Return the most derived type between \p Kind1 and \p Kind2. - /// - /// Return ASTNodeKind() if they are not related. - static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); - - /// \brief Return the most derived common ancestor between Kind1 and Kind2. - /// - /// Return ASTNodeKind() if they are not related. - static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, - ASTNodeKind Kind2); - - /// \brief Hooks for using ASTNodeKind as a key in a DenseMap. - struct DenseMapInfo { - // ASTNodeKind() is a good empty key because it is represented as a 0. - static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } - // NKI_NumberOfKinds is not a valid value, so it is good for a - // tombstone key. - static inline ASTNodeKind getTombstoneKey() { - return ASTNodeKind(NKI_NumberOfKinds); - } - static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } - static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { - return LHS.KindId == RHS.KindId; - } - }; - - /// Check if the given ASTNodeKind identifies a type that offers pointer - /// identity. This is useful for the fast path in DynTypedNode. - bool hasPointerIdentity() const { - return KindId > NKI_LastKindWithoutPointerIdentity; - } - -private: - /// \brief Kind ids. - /// - /// Includes all possible base and derived kinds. - enum NodeKindId { - NKI_None, - NKI_TemplateArgument, - NKI_NestedNameSpecifierLoc, - NKI_QualType, - NKI_TypeLoc, - NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, - NKI_CXXCtorInitializer, - NKI_NestedNameSpecifier, - NKI_Decl, -#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, -#include "clang/AST/DeclNodes.inc" - NKI_Stmt, -#define STMT(DERIVED, BASE) NKI_##DERIVED, -#include "clang/AST/StmtNodes.inc" - NKI_Type, -#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, -#include "clang/AST/TypeNodes.def" - NKI_NumberOfKinds - }; - - /// \brief Use getFromNodeKind<T>() to construct the kind. - ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} - - /// \brief Returns \c true if \c Base is a base kind of (or same as) \c - /// Derived. - /// \param Distance If non-null, used to return the distance between \c Base - /// and \c Derived in the class hierarchy. - static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); - - /// \brief Helper meta-function to convert a kind T to its enum value. - /// - /// This struct is specialized below for all known kinds. - template <class T> struct KindToKindId { - static const NodeKindId Id = NKI_None; - }; - template <class T> - struct KindToKindId<const T> : KindToKindId<T> {}; - - /// \brief Per kind info. - struct KindInfo { - /// \brief The id of the parent kind, or None if it has no parent. - NodeKindId ParentId; - /// \brief Name of the kind. - const char *Name; - }; - static const KindInfo AllKindInfo[NKI_NumberOfKinds]; - - NodeKindId KindId; -}; - -#define KIND_TO_KIND_ID(Class) \ - template <> struct ASTNodeKind::KindToKindId<Class> { \ - static const NodeKindId Id = NKI_##Class; \ - }; -KIND_TO_KIND_ID(CXXCtorInitializer) -KIND_TO_KIND_ID(TemplateArgument) -KIND_TO_KIND_ID(NestedNameSpecifier) -KIND_TO_KIND_ID(NestedNameSpecifierLoc) -KIND_TO_KIND_ID(QualType) -KIND_TO_KIND_ID(TypeLoc) -KIND_TO_KIND_ID(Decl) -KIND_TO_KIND_ID(Stmt) -KIND_TO_KIND_ID(Type) -#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) -#include "clang/AST/DeclNodes.inc" -#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) -#include "clang/AST/StmtNodes.inc" -#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) -#include "clang/AST/TypeNodes.def" -#undef KIND_TO_KIND_ID - -inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { - OS << K.asStringRef(); - return OS; -} - -/// \brief A dynamically typed AST node container. -/// -/// Stores an AST node in a type safe way. This allows writing code that -/// works with different kinds of AST nodes, despite the fact that they don't -/// have a common base class. -/// -/// Use \c create(Node) to create a \c DynTypedNode from an AST node, -/// and \c get<T>() to retrieve the node as type T if the types match. -/// -/// See \c ASTNodeKind for which node base types are currently supported; -/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of -/// the supported base types. -class DynTypedNode { -public: - /// \brief Creates a \c DynTypedNode from \c Node. - template <typename T> - static DynTypedNode create(const T &Node) { - return BaseConverter<T>::create(Node); - } - - /// \brief Retrieve the stored node as type \c T. - /// - /// Returns NULL if the stored node does not have a type that is - /// convertible to \c T. - /// - /// For types that have identity via their pointer in the AST - /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned - /// pointer points to the referenced AST node. - /// For other types (like \c QualType) the value is stored directly - /// in the \c DynTypedNode, and the returned pointer points at - /// the storage inside DynTypedNode. For those nodes, do not - /// use the pointer outside the scope of the DynTypedNode. - template <typename T> - const T *get() const { - return BaseConverter<T>::get(NodeKind, Storage.buffer); - } - - /// \brief Retrieve the stored node as type \c T. - /// - /// Similar to \c get(), but asserts that the type is what we are expecting. - template <typename T> - const T &getUnchecked() const { - return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); - } - - ASTNodeKind getNodeKind() const { return NodeKind; } - - /// \brief Returns a pointer that identifies the stored AST node. - /// - /// Note that this is not supported by all AST nodes. For AST nodes - /// that don't have a pointer-defined identity inside the AST, this - /// method returns NULL. - const void *getMemoizationData() const { - return NodeKind.hasPointerIdentity() - ? *reinterpret_cast<void *const *>(Storage.buffer) - : nullptr; - } - - /// \brief Prints the node to the given output stream. - void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; - - /// \brief Dumps the node to the given output stream. - void dump(llvm::raw_ostream &OS, SourceManager &SM) const; - - /// \brief For nodes which represent textual entities in the source code, - /// return their SourceRange. For all other nodes, return SourceRange(). - SourceRange getSourceRange() const; - - /// @{ - /// \brief Imposes an order on \c DynTypedNode. - /// - /// Supports comparison of nodes that support memoization. - /// FIXME: Implement comparsion for other node types (currently - /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). - bool operator<(const DynTypedNode &Other) const { - if (!NodeKind.isSame(Other.NodeKind)) - return NodeKind < Other.NodeKind; - - if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) - return getUnchecked<QualType>().getAsOpaquePtr() < - Other.getUnchecked<QualType>().getAsOpaquePtr(); - - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) { - auto TLA = getUnchecked<TypeLoc>(); - auto TLB = Other.getUnchecked<TypeLoc>(); - return std::make_pair(TLA.getType().getAsOpaquePtr(), - TLA.getOpaqueData()) < - std::make_pair(TLB.getType().getAsOpaquePtr(), - TLB.getOpaqueData()); - } - - if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( - NodeKind)) { - auto NNSLA = getUnchecked<NestedNameSpecifierLoc>(); - auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>(); - return std::make_pair(NNSLA.getNestedNameSpecifier(), - NNSLA.getOpaqueData()) < - std::make_pair(NNSLB.getNestedNameSpecifier(), - NNSLB.getOpaqueData()); - } - - assert(getMemoizationData() && Other.getMemoizationData()); - return getMemoizationData() < Other.getMemoizationData(); - } - bool operator==(const DynTypedNode &Other) const { - // DynTypedNode::create() stores the exact kind of the node in NodeKind. - // If they contain the same node, their NodeKind must be the same. - if (!NodeKind.isSame(Other.NodeKind)) - return false; - - // FIXME: Implement for other types. - if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) - return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); - - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) - return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>(); - - if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind)) - return getUnchecked<NestedNameSpecifierLoc>() == - Other.getUnchecked<NestedNameSpecifierLoc>(); - - assert(getMemoizationData() && Other.getMemoizationData()); - return getMemoizationData() == Other.getMemoizationData(); - } - bool operator!=(const DynTypedNode &Other) const { - return !operator==(Other); - } - /// @} - - /// \brief Hooks for using DynTypedNode as a key in a DenseMap. - struct DenseMapInfo { - static inline DynTypedNode getEmptyKey() { - DynTypedNode Node; - Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey(); - return Node; - } - static inline DynTypedNode getTombstoneKey() { - DynTypedNode Node; - Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey(); - return Node; - } - static unsigned getHashValue(const DynTypedNode &Val) { - // FIXME: Add hashing support for the remaining types. - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) { - auto TL = Val.getUnchecked<TypeLoc>(); - return llvm::hash_combine(TL.getType().getAsOpaquePtr(), - TL.getOpaqueData()); - } - - if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( - Val.NodeKind)) { - auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>(); - return llvm::hash_combine(NNSL.getNestedNameSpecifier(), - NNSL.getOpaqueData()); - } - - assert(Val.getMemoizationData()); - return llvm::hash_value(Val.getMemoizationData()); - } - static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) { - auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey(); - auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey(); - return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) && - ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) || - (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) && - ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) || - LHS == RHS; - } - }; - -private: - /// \brief Takes care of converting from and to \c T. - template <typename T, typename EnablerT = void> struct BaseConverter; - - /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. - template <typename T, typename BaseT> struct DynCastPtrConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) - return &getUnchecked(NodeKind, Storage); - return nullptr; - } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { - assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); - return *cast<T>(static_cast<const BaseT *>( - *reinterpret_cast<const void *const *>(Storage))); - } - static DynTypedNode create(const BaseT &Node) { - DynTypedNode Result; - Result.NodeKind = ASTNodeKind::getFromNode(Node); - new (Result.Storage.buffer) const void *(&Node); - return Result; - } - }; - - /// \brief Converter that stores T* (by pointer). - template <typename T> struct PtrConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) - return &getUnchecked(NodeKind, Storage); - return nullptr; - } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { - assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); - return *static_cast<const T *>( - *reinterpret_cast<const void *const *>(Storage)); - } - static DynTypedNode create(const T &Node) { - DynTypedNode Result; - Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); - new (Result.Storage.buffer) const void *(&Node); - return Result; - } - }; - - /// \brief Converter that stores T (by value). - template <typename T> struct ValueConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) - return reinterpret_cast<const T *>(Storage); - return nullptr; - } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { - assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); - return *reinterpret_cast<const T *>(Storage); - } - static DynTypedNode create(const T &Node) { - DynTypedNode Result; - Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); - new (Result.Storage.buffer) T(Node); - return Result; - } - }; - - ASTNodeKind NodeKind; - - /// \brief Stores the data of the node. - /// - /// Note that we can store \c Decls, \c Stmts, \c Types, - /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are - /// guaranteed to be unique pointers pointing to dedicated storage in the AST. - /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and - /// \c TemplateArguments on the other hand do not have storage or unique - /// pointers and thus need to be stored by value. - llvm::AlignedCharArrayUnion<const void *, TemplateArgument, - NestedNameSpecifierLoc, QualType, - TypeLoc> Storage; -}; - -template <typename T> -struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> - : public DynCastPtrConverter<T, Decl> {}; - -template <typename T> -struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> - : public DynCastPtrConverter<T, Stmt> {}; - -template <typename T> -struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> - : public DynCastPtrConverter<T, Type> {}; - -template <> -struct DynTypedNode::BaseConverter< - NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; - -template <> -struct DynTypedNode::BaseConverter< - CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; - -template <> -struct DynTypedNode::BaseConverter< - TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; - -template <> -struct DynTypedNode::BaseConverter< - NestedNameSpecifierLoc, - void> : public ValueConverter<NestedNameSpecifierLoc> {}; - -template <> -struct DynTypedNode::BaseConverter<QualType, - void> : public ValueConverter<QualType> {}; - -template <> -struct DynTypedNode::BaseConverter< - TypeLoc, void> : public ValueConverter<TypeLoc> {}; - -// The only operation we allow on unsupported types is \c get. -// This allows to conveniently use \c DynTypedNode when having an arbitrary -// AST node that is not supported, but prevents misuse - a user cannot create -// a DynTypedNode from arbitrary types. -template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - return NULL; - } -}; - -} // end namespace ast_type_traits -} // end namespace clang - -namespace llvm { - -template <> -struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> - : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; - -template <> -struct DenseMapInfo<clang::ast_type_traits::DynTypedNode> - : clang::ast_type_traits::DynTypedNode::DenseMapInfo {}; - -} // end namespace llvm - -#endif diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h deleted file mode 100644 index 9078a0e..0000000 --- a/include/clang/AST/ASTUnresolvedSet.h +++ /dev/null @@ -1,110 +0,0 @@ -//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides an UnresolvedSet-like class, whose contents are -// allocated using the allocator associated with an ASTContext. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H -#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H - -#include "clang/AST/ASTVector.h" -#include "clang/AST/UnresolvedSet.h" - -namespace clang { - -/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. -class ASTUnresolvedSet { - struct DeclsTy : ASTVector<DeclAccessPair> { - DeclsTy() {} - DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {} - - bool isLazy() const { return getTag(); } - void setLazy(bool Lazy) { setTag(Lazy); } - }; - - DeclsTy Decls; - - friend class LazyASTUnresolvedSet; - -public: - ASTUnresolvedSet() {} - ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {} - - typedef UnresolvedSetIterator iterator; - typedef UnresolvedSetIterator const_iterator; - - iterator begin() { return iterator(Decls.begin()); } - iterator end() { return iterator(Decls.end()); } - - const_iterator begin() const { return const_iterator(Decls.begin()); } - const_iterator end() const { return const_iterator(Decls.end()); } - - void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) { - Decls.push_back(DeclAccessPair::make(D, AS), C); - } - - /// Replaces the given declaration with the new one, once. - /// - /// \return true if the set changed - bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) { - for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { - if (I->getDecl() == Old) { - I->set(New, AS); - return true; - } - } - return false; - } - - void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); } - - void clear() { Decls.clear(); } - - bool empty() const { return Decls.empty(); } - unsigned size() const { return Decls.size(); } - - void reserve(ASTContext &C, unsigned N) { - Decls.reserve(C, N); - } - - void append(ASTContext &C, iterator I, iterator E) { - Decls.append(C, I.I, E.I); - } - - DeclAccessPair &operator[](unsigned I) { return Decls[I]; } - const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; } -}; - -/// \brief An UnresolvedSet-like class that might not have been loaded from the -/// external AST source yet. -class LazyASTUnresolvedSet { - mutable ASTUnresolvedSet Impl; - - void getFromExternalSource(ASTContext &C) const; - -public: - ASTUnresolvedSet &get(ASTContext &C) const { - if (Impl.Decls.isLazy()) - getFromExternalSource(C); - return Impl; - } - - void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); } - void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) { - assert(Impl.empty() || Impl.Decls.isLazy()); - Impl.Decls.setLazy(true); - Impl.addDecl(C, reinterpret_cast<NamedDecl*>(ID << 2), AS); - } -}; - -} // namespace clang - -#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h deleted file mode 100644 index 79453bf..0000000 --- a/include/clang/AST/ASTVector.h +++ /dev/null @@ -1,405 +0,0 @@ -//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides ASTVector, a vector ADT whose contents are -// allocated using the allocator associated with an ASTContext.. -// -//===----------------------------------------------------------------------===// - -// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. -// We can refactor this core logic into something common. - -#ifndef LLVM_CLANG_AST_ASTVECTOR_H -#define LLVM_CLANG_AST_ASTVECTOR_H - -#include "clang/AST/AttrIterator.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/type_traits.h" -#include <algorithm> -#include <cstring> -#include <memory> - -namespace clang { - class ASTContext; - -template<typename T> -class ASTVector { -private: - T *Begin, *End; - llvm::PointerIntPair<T*, 1, bool> Capacity; - - void setEnd(T *P) { this->End = P; } - -protected: - // Make a tag bit available to users of this class. - // FIXME: This is a horrible hack. - bool getTag() const { return Capacity.getInt(); } - void setTag(bool B) { Capacity.setInt(B); } - -public: - // Default ctor - Initialize to empty. - ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {} - - ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) { - O.Begin = O.End = nullptr; - O.Capacity.setPointer(nullptr); - O.Capacity.setInt(false); - } - - ASTVector(const ASTContext &C, unsigned N) - : Begin(nullptr), End(nullptr), Capacity(nullptr, false) { - reserve(C, N); - } - - ASTVector &operator=(ASTVector &&RHS) { - ASTVector O(std::move(RHS)); - using std::swap; - swap(Begin, O.Begin); - swap(End, O.End); - swap(Capacity, O.Capacity); - return *this; - } - - ~ASTVector() { - if (std::is_class<T>::value) { - // Destroy the constructed elements in the vector. - destroy_range(Begin, End); - } - } - - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; - - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - - // forward iterator creation methods. - iterator begin() { return Begin; } - const_iterator begin() const { return Begin; } - iterator end() { return End; } - const_iterator end() const { return End; } - - // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} - - bool empty() const { return Begin == End; } - size_type size() const { return End-Begin; } - - reference operator[](unsigned idx) { - assert(Begin + idx < End); - return Begin[idx]; - } - const_reference operator[](unsigned idx) const { - assert(Begin + idx < End); - return Begin[idx]; - } - - reference front() { - return begin()[0]; - } - const_reference front() const { - return begin()[0]; - } - - reference back() { - return end()[-1]; - } - const_reference back() const { - return end()[-1]; - } - - void pop_back() { - --End; - End->~T(); - } - - T pop_back_val() { - T Result = back(); - pop_back(); - return Result; - } - - void clear() { - if (std::is_class<T>::value) { - destroy_range(Begin, End); - } - End = Begin; - } - - /// data - Return a pointer to the vector's buffer, even if empty(). - pointer data() { - return pointer(Begin); - } - - /// data - Return a pointer to the vector's buffer, even if empty(). - const_pointer data() const { - return const_pointer(Begin); - } - - void push_back(const_reference Elt, const ASTContext &C) { - if (End < this->capacity_ptr()) { - Retry: - new (End) T(Elt); - ++End; - return; - } - grow(C); - goto Retry; - } - - void reserve(const ASTContext &C, unsigned N) { - if (unsigned(this->capacity_ptr()-Begin) < N) - grow(C, N); - } - - /// capacity - Return the total number of elements in the currently allocated - /// buffer. - size_t capacity() const { return this->capacity_ptr() - Begin; } - - /// append - Add the specified range to the end of the SmallVector. - /// - template<typename in_iter> - void append(const ASTContext &C, in_iter in_start, in_iter in_end) { - size_type NumInputs = std::distance(in_start, in_end); - - if (NumInputs == 0) - return; - - // Grow allocated space if needed. - if (NumInputs > size_type(this->capacity_ptr()-this->end())) - this->grow(C, this->size()+NumInputs); - - // Copy the new elements over. - // TODO: NEED To compile time dispatch on whether in_iter is a random access - // iterator to use the fast uninitialized_copy. - std::uninitialized_copy(in_start, in_end, this->end()); - this->setEnd(this->end() + NumInputs); - } - - /// append - Add the specified range to the end of the SmallVector. - /// - void append(const ASTContext &C, size_type NumInputs, const T &Elt) { - // Grow allocated space if needed. - if (NumInputs > size_type(this->capacity_ptr()-this->end())) - this->grow(C, this->size()+NumInputs); - - // Copy the new elements over. - std::uninitialized_fill_n(this->end(), NumInputs, Elt); - this->setEnd(this->end() + NumInputs); - } - - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory - /// starting with "Dest", constructing elements into it as needed. - template<typename It1, typename It2> - static void uninitialized_copy(It1 I, It1 E, It2 Dest) { - std::uninitialized_copy(I, E, Dest); - } - - iterator insert(const ASTContext &C, iterator I, const T &Elt) { - if (I == this->end()) { // Important special case for empty vector. - push_back(Elt, C); - return this->end()-1; - } - - if (this->End < this->capacity_ptr()) { - Retry: - new (this->end()) T(this->back()); - this->setEnd(this->end()+1); - // Push everything else over. - std::copy_backward(I, this->end()-1, this->end()); - *I = Elt; - return I; - } - size_t EltNo = I-this->begin(); - this->grow(C); - I = this->begin()+EltNo; - goto Retry; - } - - iterator insert(const ASTContext &C, iterator I, size_type NumToInsert, - const T &Elt) { - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); - - if (I == this->end()) { // Important special case for empty vector. - append(C, NumToInsert, Elt); - return this->begin() + InsertElt; - } - - // Ensure there is enough space. - reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); - - // Uninvalidate the iterator. - I = this->begin()+InsertElt; - - // If there are more elements between the insertion point and the end of the - // range than there are being inserted, we can use a simple approach to - // insertion. Since we already reserved space, we know that this won't - // reallocate the vector. - if (size_t(this->end()-I) >= NumToInsert) { - T *OldEnd = this->end(); - append(C, this->end()-NumToInsert, this->end()); - - // Copy the existing elements that get replaced. - std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - - std::fill_n(I, NumToInsert, Elt); - return I; - } - - // Otherwise, we're inserting more elements than exist already, and we're - // not inserting at the end. - - // Copy over the elements that we're about to overwrite. - T *OldEnd = this->end(); - this->setEnd(this->end() + NumToInsert); - size_t NumOverwritten = OldEnd-I; - this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); - - // Replace the overwritten part. - std::fill_n(I, NumOverwritten, Elt); - - // Insert the non-overwritten middle part. - std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); - return I; - } - - template<typename ItTy> - iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) { - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); - - if (I == this->end()) { // Important special case for empty vector. - append(C, From, To); - return this->begin() + InsertElt; - } - - size_t NumToInsert = std::distance(From, To); - - // Ensure there is enough space. - reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); - - // Uninvalidate the iterator. - I = this->begin()+InsertElt; - - // If there are more elements between the insertion point and the end of the - // range than there are being inserted, we can use a simple approach to - // insertion. Since we already reserved space, we know that this won't - // reallocate the vector. - if (size_t(this->end()-I) >= NumToInsert) { - T *OldEnd = this->end(); - append(C, this->end()-NumToInsert, this->end()); - - // Copy the existing elements that get replaced. - std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - - std::copy(From, To, I); - return I; - } - - // Otherwise, we're inserting more elements than exist already, and we're - // not inserting at the end. - - // Copy over the elements that we're about to overwrite. - T *OldEnd = this->end(); - this->setEnd(this->end() + NumToInsert); - size_t NumOverwritten = OldEnd-I; - this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); - - // Replace the overwritten part. - for (; NumOverwritten > 0; --NumOverwritten) { - *I = *From; - ++I; ++From; - } - - // Insert the non-overwritten middle part. - this->uninitialized_copy(From, To, OldEnd); - return I; - } - - void resize(const ASTContext &C, unsigned N, const T &NV) { - if (N < this->size()) { - this->destroy_range(this->begin()+N, this->end()); - this->setEnd(this->begin()+N); - } else if (N > this->size()) { - if (this->capacity() < N) - this->grow(C, N); - construct_range(this->end(), this->begin()+N, NV); - this->setEnd(this->begin()+N); - } - } - -private: - /// grow - double the size of the allocated memory, guaranteeing space for at - /// least one more element or MinSize if specified. - void grow(const ASTContext &C, size_type MinSize = 1); - - void construct_range(T *S, T *E, const T &Elt) { - for (; S != E; ++S) - new (S) T(Elt); - } - - void destroy_range(T *S, T *E) { - while (S != E) { - --E; - E->~T(); - } - } - -protected: - const_iterator capacity_ptr() const { - return (iterator) Capacity.getPointer(); - } - iterator capacity_ptr() { return (iterator)Capacity.getPointer(); } -}; - -// Define this out-of-line to dissuade the C++ compiler from inlining it. -template <typename T> -void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) { - size_t CurCapacity = this->capacity(); - size_t CurSize = size(); - size_t NewCapacity = 2*CurCapacity; - if (NewCapacity < MinSize) - NewCapacity = MinSize; - - // Allocate the memory from the ASTContext. - T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity]; - - // Copy the elements over. - if (Begin != End) { - if (std::is_class<T>::value) { - std::uninitialized_copy(Begin, End, NewElts); - // Destroy the original elements. - destroy_range(Begin, End); - } else { - // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). - memcpy(NewElts, Begin, CurSize * sizeof(T)); - } - } - - // ASTContext never frees any memory. - Begin = NewElts; - End = NewElts+CurSize; - Capacity.setPointer(Begin+NewCapacity); -} - -} // end: clang namespace -#endif diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h deleted file mode 100644 index 8b80e9f..0000000 --- a/include/clang/AST/Attr.h +++ /dev/null @@ -1,169 +0,0 @@ -//===--- Attr.h - Classes for representing attributes ----------*- 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 Attr interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ATTR_H -#define LLVM_CLANG_AST_ATTR_H - -#include "clang/AST/AttrIterator.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/Basic/AttrKinds.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Sanitizers.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/VersionTuple.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> - -namespace clang { - class ASTContext; - class IdentifierInfo; - class ObjCInterfaceDecl; - class Expr; - class QualType; - class FunctionDecl; - class TypeSourceInfo; - -/// Attr - This represents one attribute. -class Attr { -private: - SourceRange Range; - unsigned AttrKind : 16; - -protected: - /// An index into the spelling list of an - /// attribute defined in Attr.td file. - unsigned SpellingListIndex : 4; - bool Inherited : 1; - bool IsPackExpansion : 1; - bool Implicit : 1; - bool IsLateParsed : 1; - bool DuplicatesAllowed : 1; - - void *operator new(size_t bytes) LLVM_NOEXCEPT { - llvm_unreachable("Attrs cannot be allocated with regular 'new'."); - } - void operator delete(void *data) LLVM_NOEXCEPT { - llvm_unreachable("Attrs cannot be released with regular 'delete'."); - } - -public: - // Forward so that the regular new and delete do not hide global ones. - void *operator new(size_t Bytes, ASTContext &C, - size_t Alignment = 8) LLVM_NOEXCEPT { - return ::operator new(Bytes, C, Alignment); - } - void operator delete(void *Ptr, ASTContext &C, - size_t Alignment) LLVM_NOEXCEPT { - return ::operator delete(Ptr, C, Alignment); - } - -protected: - Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) - : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), - Inherited(false), IsPackExpansion(false), Implicit(false), - IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {} - -public: - - attr::Kind getKind() const { - return static_cast<attr::Kind>(AttrKind); - } - - unsigned getSpellingListIndex() const { return SpellingListIndex; } - const char *getSpelling() const; - - SourceLocation getLocation() const { return Range.getBegin(); } - SourceRange getRange() const { return Range; } - void setRange(SourceRange R) { Range = R; } - - bool isInherited() const { return Inherited; } - - /// \brief Returns true if the attribute has been implicitly created instead - /// of explicitly written by the user. - bool isImplicit() const { return Implicit; } - void setImplicit(bool I) { Implicit = I; } - - void setPackExpansion(bool PE) { IsPackExpansion = PE; } - bool isPackExpansion() const { return IsPackExpansion; } - - // Clone this attribute. - Attr *clone(ASTContext &C) const; - - bool isLateParsed() const { return IsLateParsed; } - - // Pretty print this attribute. - void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; - - /// \brief By default, attributes cannot be duplicated when being merged; - /// however, an attribute can override this. Returns true if the attribute - /// can be duplicated when merging. - bool duplicatesAllowed() const { return DuplicatesAllowed; } -}; - -class InheritableAttr : public Attr { -protected: - InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) - : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} - -public: - void setInherited(bool I) { Inherited = I; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() <= attr::LAST_INHERITABLE; - } -}; - -class InheritableParamAttr : public InheritableAttr { -protected: - InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) - : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed, - DuplicatesAllowed) {} - -public: - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - // Relies on relative order of enum emission with respect to MS inheritance - // attrs. - return A->getKind() <= attr::LAST_INHERITABLE_PARAM; - } -}; - -#include "clang/AST/Attrs.inc" - -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const Attr *At) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), - DiagnosticsEngine::ak_attr); - return DB; -} - -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const Attr *At) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(At), - DiagnosticsEngine::ak_attr); - return PD; -} -} // end namespace clang - -#endif diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h deleted file mode 100644 index a0c8030..0000000 --- a/include/clang/AST/AttrIterator.h +++ /dev/null @@ -1,142 +0,0 @@ -//===--- AttrIterator.h - Classes for attribute iteration -------*- 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 Attr vector and specific_attr_iterator interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_ATTRITERATOR_H -#define LLVM_CLANG_AST_ATTRITERATOR_H - -#include "clang/Basic/LLVM.h" -#include <iterator> - -namespace clang { - class ASTContext; - class Attr; -} - -// Defined in ASTContext.h -void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment = 8); -// FIXME: Being forced to not have a default argument here due to redeclaration -// rules on default arguments sucks -void *operator new[](size_t Bytes, const clang::ASTContext &C, - size_t Alignment); - -// 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, const clang::ASTContext &C, size_t); -void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); - -namespace clang { - -/// AttrVec - A vector of Attr, which is how they are stored on the AST. -typedef SmallVector<Attr*, 2> AttrVec; -typedef SmallVector<const Attr*, 2> ConstAttrVec; - -/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only -/// providing attributes that are of a specific type. -template <typename SpecificAttr, typename Container = AttrVec> -class specific_attr_iterator { - typedef typename Container::const_iterator Iterator; - - /// Current - The current, underlying iterator. - /// In order to ensure we don't dereference an invalid iterator unless - /// specifically requested, we don't necessarily advance this all the - /// way. Instead, we advance it when an operation is requested; if the - /// operation is acting on what should be a past-the-end iterator, - /// then we offer no guarantees, but this way we do not dereference a - /// past-the-end iterator when we move to a past-the-end position. - mutable Iterator Current; - - void AdvanceToNext() const { - while (!isa<SpecificAttr>(*Current)) - ++Current; - } - - void AdvanceToNext(Iterator I) const { - while (Current != I && !isa<SpecificAttr>(*Current)) - ++Current; - } - -public: - typedef SpecificAttr* value_type; - typedef SpecificAttr* reference; - typedef SpecificAttr* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - specific_attr_iterator() : Current() { } - explicit specific_attr_iterator(Iterator i) : Current(i) { } - - reference operator*() const { - AdvanceToNext(); - return cast<SpecificAttr>(*Current); - } - pointer operator->() const { - AdvanceToNext(); - return cast<SpecificAttr>(*Current); - } - - specific_attr_iterator& operator++() { - ++Current; - return *this; - } - specific_attr_iterator operator++(int) { - specific_attr_iterator Tmp(*this); - ++(*this); - return Tmp; - } - - friend bool operator==(specific_attr_iterator Left, - specific_attr_iterator Right) { - assert((Left.Current == nullptr) == (Right.Current == nullptr)); - if (Left.Current < Right.Current) - Left.AdvanceToNext(Right.Current); - else - Right.AdvanceToNext(Left.Current); - return Left.Current == Right.Current; - } - friend bool operator!=(specific_attr_iterator Left, - specific_attr_iterator Right) { - return !(Left == Right); - } -}; - -template <typename SpecificAttr, typename Container> -inline specific_attr_iterator<SpecificAttr, Container> - specific_attr_begin(const Container& container) { - return specific_attr_iterator<SpecificAttr, Container>(container.begin()); -} -template <typename SpecificAttr, typename Container> -inline specific_attr_iterator<SpecificAttr, Container> - specific_attr_end(const Container& container) { - return specific_attr_iterator<SpecificAttr, Container>(container.end()); -} - -template <typename SpecificAttr, typename Container> -inline bool hasSpecificAttr(const Container& container) { - return specific_attr_begin<SpecificAttr>(container) != - specific_attr_end<SpecificAttr>(container); -} -template <typename SpecificAttr, typename Container> -inline SpecificAttr *getSpecificAttr(const Container& container) { - specific_attr_iterator<SpecificAttr, Container> i = - specific_attr_begin<SpecificAttr>(container); - if (i != specific_attr_end<SpecificAttr>(container)) - return *i; - else - return nullptr; -} - -} // end namespace clang - -#endif diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h deleted file mode 100644 index da538e3..0000000 --- a/include/clang/AST/BaseSubobject.h +++ /dev/null @@ -1,87 +0,0 @@ -//===--- BaseSubobject.h - BaseSubobject class ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a definition of the BaseSubobject class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H -#define LLVM_CLANG_AST_BASESUBOBJECT_H - -#include "clang/AST/CharUnits.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/type_traits.h" - -namespace clang { - class CXXRecordDecl; - -// BaseSubobject - Uniquely identifies a direct or indirect base class. -// Stores both the base class decl and the offset from the most derived class to -// the base class. Used for vtable and VTT generation. -class BaseSubobject { - /// Base - The base class declaration. - const CXXRecordDecl *Base; - - /// BaseOffset - The offset from the most derived class to the base class. - CharUnits BaseOffset; - -public: - BaseSubobject() { } - BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset) - : Base(Base), BaseOffset(BaseOffset) { } - - /// getBase - Returns the base class declaration. - const CXXRecordDecl *getBase() const { return Base; } - - /// getBaseOffset - Returns the base class offset. - CharUnits getBaseOffset() const { return BaseOffset; } - - friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) { - return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset; - } -}; - -} // end namespace clang - -namespace llvm { - -template<> struct DenseMapInfo<clang::BaseSubobject> { - static clang::BaseSubobject getEmptyKey() { - return clang::BaseSubobject( - DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(), - clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey())); - } - - static clang::BaseSubobject getTombstoneKey() { - return clang::BaseSubobject( - DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(), - clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey())); - } - - static unsigned getHashValue(const clang::BaseSubobject &Base) { - typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy; - return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(), - Base.getBaseOffset())); - } - - static bool isEqual(const clang::BaseSubobject &LHS, - const clang::BaseSubobject &RHS) { - return LHS == RHS; - } -}; - -// It's OK to treat BaseSubobject as a POD type. -template <> struct isPodLike<clang::BaseSubobject> { - static const bool value = true; -}; - -} - -#endif diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def deleted file mode 100644 index 85e237a..0000000 --- a/include/clang/AST/BuiltinTypes.def +++ /dev/null @@ -1,261 +0,0 @@ -//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- 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 database about various builtin singleton types. -// -// BuiltinType::Id is the enumerator defining the type. -// -// Context.SingletonId is the global singleton of this type. Some global -// singletons are shared by multiple types. -// -// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been -// covered by any other #define. Defining this macro covers all -// the builtins. -// -// SIGNED_TYPE(Id, SingletonId) - A signed integral type. -// -// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type. -// -// FLOATING_TYPE(Id, SingletonId) - A floating-point type. -// -// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder -// types are used to perform context-sensitive checking of specific -// forms of expression. -// -// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds -// to a builtin which uses a shared singleton type. -// -//===----------------------------------------------------------------------===// - -#ifndef SIGNED_TYPE -#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) -#endif - -#ifndef UNSIGNED_TYPE -#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) -#endif - -#ifndef FLOATING_TYPE -#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) -#endif - -#ifndef PLACEHOLDER_TYPE -#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) -#endif - -#ifndef SHARED_SINGLETON_TYPE -#define SHARED_SINGLETON_TYPE(Expansion) Expansion -#endif - -//===- Builtin Types ------------------------------------------------------===// - -// void -BUILTIN_TYPE(Void, VoidTy) - -//===- Unsigned Types -----------------------------------------------------===// - -// 'bool' in C++, '_Bool' in C99 -UNSIGNED_TYPE(Bool, BoolTy) - -// 'char' for targets where it's unsigned -SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy)) - -// 'unsigned char', explicitly qualified -UNSIGNED_TYPE(UChar, UnsignedCharTy) - -// 'wchar_t' for targets where it's unsigned -SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) - -// 'char16_t' in C++ -UNSIGNED_TYPE(Char16, Char16Ty) - -// 'char32_t' in C++ -UNSIGNED_TYPE(Char32, Char32Ty) - -// 'unsigned short' -UNSIGNED_TYPE(UShort, UnsignedShortTy) - -// 'unsigned int' -UNSIGNED_TYPE(UInt, UnsignedIntTy) - -// 'unsigned long' -UNSIGNED_TYPE(ULong, UnsignedLongTy) - -// 'unsigned long long' -UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy) - -// '__uint128_t' -UNSIGNED_TYPE(UInt128, UnsignedInt128Ty) - -//===- Signed Types -------------------------------------------------------===// - -// 'char' for targets where it's signed -SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy)) - -// 'signed char', explicitly qualified -SIGNED_TYPE(SChar, SignedCharTy) - -// 'wchar_t' for targets where it's signed -SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy)) - -// 'short' or 'signed short' -SIGNED_TYPE(Short, ShortTy) - -// 'int' or 'signed int' -SIGNED_TYPE(Int, IntTy) - -// 'long' or 'signed long' -SIGNED_TYPE(Long, LongTy) - -// 'long long' or 'signed long long' -SIGNED_TYPE(LongLong, LongLongTy) - -// '__int128_t' -SIGNED_TYPE(Int128, Int128Ty) - -//===- Floating point types -----------------------------------------------===// - -// 'half' in OpenCL, '__fp16' in ARM NEON. -FLOATING_TYPE(Half, HalfTy) - -// 'float' -FLOATING_TYPE(Float, FloatTy) - -// 'double' -FLOATING_TYPE(Double, DoubleTy) - -// 'long double' -FLOATING_TYPE(LongDouble, LongDoubleTy) - -//===- Language-specific types --------------------------------------------===// - -// This is the type of C++0x 'nullptr'. -BUILTIN_TYPE(NullPtr, NullPtrTy) - -// The primitive Objective C 'id' type. The user-visible 'id' -// type is a typedef of an ObjCObjectPointerType to an -// ObjCObjectType with this as its base. In fact, this only ever -// shows up in an AST as the base type of an ObjCObjectType. -BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy) - -// The primitive Objective C 'Class' type. The user-visible -// 'Class' type is a typedef of an ObjCObjectPointerType to an -// ObjCObjectType with this as its base. In fact, this only ever -// shows up in an AST as the base type of an ObjCObjectType. -BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy) - -// The primitive Objective C 'SEL' type. The user-visible 'SEL' -// type is a typedef of a PointerType to this. -BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy) - -// OpenCL image types. -BUILTIN_TYPE(OCLImage1d, OCLImage1dTy) -BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy) -BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy) -BUILTIN_TYPE(OCLImage2d, OCLImage2dTy) -BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy) -BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy) -BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy) -BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy) -BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy) -BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy) -BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy) -BUILTIN_TYPE(OCLImage3d, OCLImage3dTy) - -// OpenCL sampler_t. -BUILTIN_TYPE(OCLSampler, OCLSamplerTy) - -// OpenCL event_t. -BUILTIN_TYPE(OCLEvent, OCLEventTy) - -// OpenCL clk_event_t. -BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy) - -// OpenCL queue_t. -BUILTIN_TYPE(OCLQueue, OCLQueueTy) - -// OpenCL ndrange_t. -BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy) - -// OpenCL reserve_id_t. -BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy) - -// 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. -BUILTIN_TYPE(Dependent, DependentTy) - -// The type of an unresolved overload set. A placeholder type. -// Expressions with this type have one of the following basic -// forms, with parentheses generally permitted: -// foo # possibly qualified, not if an implicit access -// foo # possibly qualified, not if an implicit access -// &foo # possibly qualified, not if an implicit access -// x->foo # only if might be a static member function -// &x->foo # only if might be a static member function -// &Class::foo # when a pointer-to-member; sub-expr also has this type -// OverloadExpr::find can be used to analyze the expression. -// -// Overload should be the first placeholder type, or else change -// BuiltinType::isNonOverloadPlaceholderType() -PLACEHOLDER_TYPE(Overload, OverloadTy) - -// The type of a bound C++ non-static member function. -// A placeholder type. Expressions with this type have one of the -// following basic forms: -// foo # if an implicit access -// x->foo # if only contains non-static members -PLACEHOLDER_TYPE(BoundMember, BoundMemberTy) - -// The type of an expression which refers to a pseudo-object, -// such as those introduced by Objective C's @property or -// VS.NET's __property declarations. A placeholder type. The -// pseudo-object is actually accessed by emitting a call to -// some sort of function or method; typically there is a pair -// of a setter and a getter, with the setter used if the -// pseudo-object reference is used syntactically as the -// left-hand-side of an assignment operator. -// -// A pseudo-object reference naming an Objective-C @property is -// always a dot access with a base of object-pointer type, -// e.g. 'x.foo'. -// -// In VS.NET, a __property declaration creates an implicit -// member with an associated name, which can then be named -// in any of the normal ways an ordinary member could be. -PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy) - -// __builtin_any_type. A placeholder type. Useful for clients -// like debuggers that don't know what type to give something. -// Only a small number of operations are valid on expressions of -// unknown type, most notably explicit casts. -PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy) - -PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy) - -// The type of a cast which, in ARC, would normally require a -// __bridge, but which might be okay depending on the immediate -// context. -PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy) - -// A placeholder type for OpenMP array sections. -PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy) - -#ifdef LAST_BUILTIN_TYPE -LAST_BUILTIN_TYPE(OMPArraySection) -#undef LAST_BUILTIN_TYPE -#endif - -#undef SHARED_SINGLETON_TYPE -#undef PLACEHOLDER_TYPE -#undef FLOATING_TYPE -#undef SIGNED_TYPE -#undef UNSIGNED_TYPE -#undef BUILTIN_TYPE diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt deleted file mode 100644 index 260734f..0000000 --- a/include/clang/AST/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -clang_tablegen(Attrs.inc -gen-clang-attr-classes - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrClasses) - -clang_tablegen(AttrImpl.inc -gen-clang-attr-impl - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrImpl) - -clang_tablegen(AttrDump.inc -gen-clang-attr-dump - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrDump) - -clang_tablegen(AttrVisitor.inc -gen-clang-attr-ast-visitor - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrVisitor) - -clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes - SOURCE ../Basic/StmtNodes.td - TARGET ClangStmtNodes) - -clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes - SOURCE ../Basic/DeclNodes.td - TARGET ClangDeclNodes) - -clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes - SOURCE ../Basic/CommentNodes.td - TARGET ClangCommentNodes) - -clang_tablegen(CommentHTMLTags.inc -gen-clang-comment-html-tags - SOURCE CommentHTMLTags.td - TARGET ClangCommentHTMLTags) - -clang_tablegen(CommentHTMLTagsProperties.inc -gen-clang-comment-html-tags-properties - SOURCE CommentHTMLTags.td - TARGET ClangCommentHTMLTagsProperties) - -clang_tablegen(CommentHTMLNamedCharacterReferences.inc -gen-clang-comment-html-named-character-references - SOURCE CommentHTMLNamedCharacterReferences.td - TARGET ClangCommentHTMLNamedCharacterReferences) - -clang_tablegen(CommentCommandInfo.inc -gen-clang-comment-command-info - SOURCE CommentCommands.td - TARGET ClangCommentCommandInfo) - -clang_tablegen(CommentCommandList.inc -gen-clang-comment-command-list - SOURCE CommentCommands.td - TARGET ClangCommentCommandList) - diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h deleted file mode 100644 index 8587260..0000000 --- a/include/clang/AST/CXXInheritance.h +++ /dev/null @@ -1,365 +0,0 @@ -//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides routines that help analyzing C++ inheritance hierarchies. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H -#define LLVM_CLANG_AST_CXXINHERITANCE_H - -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include <cassert> -#include <list> -#include <map> - -namespace clang { - -class CXXBaseSpecifier; -class CXXMethodDecl; -class CXXRecordDecl; -class NamedDecl; - -/// \brief Represents an element in a path from a derived class to a -/// base class. -/// -/// Each step in the path references the link from a -/// derived class to one of its direct base classes, along with a -/// base "number" that identifies which base subobject of the -/// original derived class we are referencing. -struct CXXBasePathElement { - /// \brief The base specifier that states the link from a derived - /// class to a base class, which will be followed by this base - /// path element. - const CXXBaseSpecifier *Base; - - /// \brief The record decl of the class that the base is a base of. - const CXXRecordDecl *Class; - - /// \brief Identifies which base class subobject (of type - /// \c Base->getType()) this base path element refers to. - /// - /// This value is only valid if \c !Base->isVirtual(), because there - /// is no base numbering for the zero or one virtual bases of a - /// given type. - int SubobjectNumber; -}; - -/// \brief Represents a path from a specific derived class -/// (which is not represented as part of the path) to a particular -/// (direct or indirect) base class subobject. -/// -/// Individual elements in the path are described by the \c CXXBasePathElement -/// structure, which captures both the link from a derived class to one of its -/// direct bases and identification describing which base class -/// subobject is being used. -class CXXBasePath : public SmallVector<CXXBasePathElement, 4> { -public: - CXXBasePath() : Access(AS_public) {} - - /// \brief The access along this inheritance path. This is only - /// calculated when recording paths. AS_none is a special value - /// used to indicate a path which permits no legal access. - AccessSpecifier Access; - - /// \brief The set of declarations found inside this base class - /// subobject. - DeclContext::lookup_result Decls; - - void clear() { - SmallVectorImpl<CXXBasePathElement>::clear(); - Access = AS_public; - } -}; - -/// BasePaths - Represents the set of paths from a derived class to -/// one of its (direct or indirect) bases. For example, given the -/// following class hierarchy: -/// -/// @code -/// class A { }; -/// class B : public A { }; -/// class C : public A { }; -/// class D : public B, public C{ }; -/// @endcode -/// -/// There are two potential BasePaths to represent paths from D to a -/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0) -/// and another is (D,0)->(C,0)->(A,1). These two paths actually -/// refer to two different base class subobjects of the same type, -/// so the BasePaths object refers to an ambiguous path. On the -/// other hand, consider the following class hierarchy: -/// -/// @code -/// class A { }; -/// class B : public virtual A { }; -/// class C : public virtual A { }; -/// class D : public B, public C{ }; -/// @endcode -/// -/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0) -/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them -/// refer to the same base class subobject of type A (the virtual -/// one), there is no ambiguity. -class CXXBasePaths { - /// \brief The type from which this search originated. - CXXRecordDecl *Origin; - - /// Paths - The actual set of paths that can be taken from the - /// derived class to the same base class. - std::list<CXXBasePath> Paths; - - /// ClassSubobjects - Records the class subobjects for each class - /// type that we've seen. The first element in the pair says - /// whether we found a path to a virtual base for that class type, - /// while the element contains the number of non-virtual base - /// class subobjects for that class type. The key of the map is - /// the cv-unqualified canonical type of the base class subobject. - llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects; - - /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find - /// ambiguous paths while it is looking for a path from a derived - /// type to a base type. - bool FindAmbiguities; - - /// RecordPaths - Whether Sema::IsDerivedFrom should record paths - /// while it is determining whether there are paths from a derived - /// type to a base type. - bool RecordPaths; - - /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search - /// if it finds a path that goes across a virtual base. The virtual class - /// is also recorded. - bool DetectVirtual; - - /// ScratchPath - A BasePath that is used by Sema::lookupInBases - /// to help build the set of paths. - CXXBasePath ScratchPath; - - /// DetectedVirtual - The base class that is virtual. - const RecordType *DetectedVirtual; - - /// \brief Array of the declarations that have been found. This - /// array is constructed only if needed, e.g., to iterate over the - /// results within LookupResult. - std::unique_ptr<NamedDecl *[]> DeclsFound; - unsigned NumDeclsFound; - - friend class CXXRecordDecl; - - void ComputeDeclsFound(); - - bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback BaseMatches); - -public: - typedef std::list<CXXBasePath>::iterator paths_iterator; - typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; - typedef NamedDecl **decl_iterator; - - /// BasePaths - Construct a new BasePaths structure to record the - /// paths for a derived-to-base search. - explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true, - bool DetectVirtual = true) - : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(nullptr), - NumDeclsFound(0) {} - - paths_iterator begin() { return Paths.begin(); } - paths_iterator end() { return Paths.end(); } - const_paths_iterator begin() const { return Paths.begin(); } - const_paths_iterator end() const { return Paths.end(); } - - CXXBasePath& front() { return Paths.front(); } - const CXXBasePath& front() const { return Paths.front(); } - - typedef llvm::iterator_range<decl_iterator> decl_range; - decl_range found_decls(); - - /// \brief Determine whether the path from the most-derived type to the - /// given base type is ambiguous (i.e., it refers to multiple subobjects of - /// the same base type). - bool isAmbiguous(CanQualType BaseType); - - /// \brief Whether we are finding multiple paths to detect ambiguities. - bool isFindingAmbiguities() const { return FindAmbiguities; } - - /// \brief Whether we are recording paths. - bool isRecordingPaths() const { return RecordPaths; } - - /// \brief Specify whether we should be recording paths or not. - void setRecordingPaths(bool RP) { RecordPaths = RP; } - - /// \brief Whether we are detecting virtual bases. - bool isDetectingVirtual() const { return DetectVirtual; } - - /// \brief The virtual base discovered on the path (if we are merely - /// detecting virtuals). - const RecordType* getDetectedVirtual() const { - return DetectedVirtual; - } - - /// \brief Retrieve the type from which this base-paths search - /// began - CXXRecordDecl *getOrigin() const { return Origin; } - void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; } - - /// \brief Clear the base-paths results. - void clear(); - - /// \brief Swap this data structure's contents with another CXXBasePaths - /// object. - void swap(CXXBasePaths &Other); -}; - -/// \brief Uniquely identifies a virtual method within a class -/// hierarchy by the method itself and a class subobject number. -struct UniqueVirtualMethod { - UniqueVirtualMethod() - : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { } - - UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, - const CXXRecordDecl *InVirtualSubobject) - : Method(Method), Subobject(Subobject), - InVirtualSubobject(InVirtualSubobject) { } - - /// \brief The overriding virtual method. - CXXMethodDecl *Method; - - /// \brief The subobject in which the overriding virtual method - /// resides. - unsigned Subobject; - - /// \brief The virtual base class subobject of which this overridden - /// virtual method is a part. Note that this records the closest - /// derived virtual base class subobject. - const CXXRecordDecl *InVirtualSubobject; - - friend bool operator==(const UniqueVirtualMethod &X, - const UniqueVirtualMethod &Y) { - return X.Method == Y.Method && X.Subobject == Y.Subobject && - X.InVirtualSubobject == Y.InVirtualSubobject; - } - - friend bool operator!=(const UniqueVirtualMethod &X, - const UniqueVirtualMethod &Y) { - return !(X == Y); - } -}; - -/// \brief The set of methods that override a given virtual method in -/// each subobject where it occurs. -/// -/// The first part of the pair is the subobject in which the -/// overridden virtual function occurs, while the second part of the -/// pair is the virtual method that overrides it (including the -/// subobject in which that virtual function occurs). -class OverridingMethods { - typedef SmallVector<UniqueVirtualMethod, 4> ValuesT; - typedef llvm::MapVector<unsigned, ValuesT> MapType; - MapType Overrides; - -public: - // Iterate over the set of subobjects that have overriding methods. - typedef MapType::iterator iterator; - typedef MapType::const_iterator const_iterator; - iterator begin() { return Overrides.begin(); } - const_iterator begin() const { return Overrides.begin(); } - iterator end() { return Overrides.end(); } - const_iterator end() const { return Overrides.end(); } - unsigned size() const { return Overrides.size(); } - - // Iterate over the set of overriding virtual methods in a given - // subobject. - typedef SmallVectorImpl<UniqueVirtualMethod>::iterator - overriding_iterator; - typedef SmallVectorImpl<UniqueVirtualMethod>::const_iterator - overriding_const_iterator; - - // Add a new overriding method for a particular subobject. - void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding); - - // Add all of the overriding methods from "other" into overrides for - // this method. Used when merging the overrides from multiple base - // class subobjects. - void add(const OverridingMethods &Other); - - // Replace all overriding virtual methods in all subobjects with the - // given virtual method. - void replaceAll(UniqueVirtualMethod Overriding); -}; - -/// \brief A mapping from each virtual member function to its set of -/// final overriders. -/// -/// Within a class hierarchy for a given derived class, each virtual -/// member function in that hierarchy has one or more "final -/// overriders" (C++ [class.virtual]p2). A final overrider for a -/// virtual function "f" is the virtual function that will actually be -/// invoked when dispatching a call to "f" through the -/// vtable. Well-formed classes have a single final overrider for each -/// virtual function; in abstract classes, the final overrider for at -/// least one virtual function is a pure virtual function. Due to -/// multiple, virtual inheritance, it is possible for a class to have -/// more than one final overrider. Athough this is an error (per C++ -/// [class.virtual]p2), it is not considered an error here: the final -/// overrider map can represent multiple final overriders for a -/// method, and it is up to the client to determine whether they are -/// problem. For example, the following class \c D has two final -/// overriders for the virtual function \c A::f(), one in \c C and one -/// in \c D: -/// -/// \code -/// struct A { virtual void f(); }; -/// struct B : virtual A { virtual void f(); }; -/// struct C : virtual A { virtual void f(); }; -/// struct D : B, C { }; -/// \endcode -/// -/// This data structure contains a mapping from every virtual -/// function *that does not override an existing virtual function* and -/// in every subobject where that virtual function occurs to the set -/// of virtual functions that override it. Thus, the same virtual -/// function \c A::f can actually occur in multiple subobjects of type -/// \c A due to multiple inheritance, and may be overridden by -/// different virtual functions in each, as in the following example: -/// -/// \code -/// struct A { virtual void f(); }; -/// struct B : A { virtual void f(); }; -/// struct C : A { virtual void f(); }; -/// struct D : B, C { }; -/// \endcode -/// -/// Unlike in the previous example, where the virtual functions \c -/// B::f and \c C::f both overrode \c A::f in the same subobject of -/// type \c A, in this example the two virtual functions both override -/// \c A::f but in *different* subobjects of type A. This is -/// represented by numbering the subobjects in which the overridden -/// and the overriding virtual member functions are located. Subobject -/// 0 represents the virtual base class subobject of that type, while -/// subobject numbers greater than 0 refer to non-virtual base class -/// subobjects of that type. -class CXXFinalOverriderMap - : public llvm::MapVector<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 deleted file mode 100644 index b25800b..0000000 --- a/include/clang/AST/CanonicalType.h +++ /dev/null @@ -1,665 +0,0 @@ -//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the CanQual class template, which provides access to -// canonical types. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_CANONICALTYPE_H -#define LLVM_CLANG_AST_CANONICALTYPE_H - -#include "clang/AST/Type.h" -#include "llvm/ADT/iterator.h" -#include "llvm/Support/Casting.h" - -namespace clang { - -template<typename T> class CanProxy; -template<typename T> struct CanProxyAdaptor; - -//----------------------------------------------------------------------------// -// Canonical, qualified type template -//----------------------------------------------------------------------------// - -/// \brief Represents a canonical, potentially-qualified type. -/// -/// The CanQual template is a lightweight smart pointer that provides access -/// to the canonical representation of a type, where all typedefs and other -/// syntactic sugar has been eliminated. A CanQualType may also have various -/// qualifiers (const, volatile, restrict) attached to it. -/// -/// The template type parameter @p T is one of the Type classes (PointerType, -/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that -/// type (or some subclass of that type). The typedef @c CanQualType is just -/// a shorthand for @c CanQual<Type>. -/// -/// An instance of @c CanQual<T> can be implicitly converted to a -/// @c CanQual<U> when T is derived from U, which essentially provides an -/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be -/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can -/// be implicitly converted to a QualType, but the reverse operation requires -/// a call to ASTContext::getCanonicalType(). -/// -/// -template<typename T = Type> -class CanQual { - /// \brief The actual, canonical type. - QualType Stored; - -public: - /// \brief Constructs a NULL canonical type. - CanQual() : Stored() { } - - /// \brief Converting constructor that permits implicit upcasting of - /// canonical type pointers. - template <typename U> - CanQual(const CanQual<U> &Other, - typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); - - /// \brief Retrieve the underlying type pointer, which refers to a - /// canonical type. - /// - /// 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; } - - /// \brief Implicit conversion to bool. - explicit operator bool() const { return !isNull(); } - - bool isNull() const { - 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. - /// - /// The getAs() function is typically used to try to downcast to a - /// more specific (canonical) type in the type system. For example: - /// - /// @code - /// void f(CanQual<Type> T) { - /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { - /// // look at Ptr's pointee type - /// } - /// } - /// @endcode - /// - /// \returns A proxy pointer to the same type, but with the specified - /// static type (@p U). If the dynamic type is not the specified static type - /// or a derived class thereof, a NULL canonical type. - template<typename U> CanProxy<U> getAs() const; - - template<typename U> CanProxy<U> castAs() const; - - /// \brief Overloaded arrow operator that produces a canonical type - /// proxy. - CanProxy<T> operator->() const; - - /// \brief Retrieve all qualifiers. - Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } - - /// \brief Retrieve the const/volatile/restrict qualifiers. - unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } - - /// \brief Determines whether this type has any qualifiers - bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } - - bool isConstQualified() const { - return Stored.isLocalConstQualified(); - } - bool isVolatileQualified() const { - return Stored.isLocalVolatileQualified(); - } - bool isRestrictQualified() const { - return Stored.isLocalRestrictQualified(); - } - - /// \brief Determines if this canonical type is furthermore - /// canonical as a parameter. The parameter-canonicalization - /// process decays arrays to pointers and drops top-level qualifiers. - bool isCanonicalAsParam() const { - return Stored.isCanonicalAsParam(); - } - - /// \brief Retrieve the unqualified form of this type. - CanQual<T> getUnqualifiedType() const; - - /// \brief Retrieves a version of this type with const applied. - /// Note that this does not always yield a canonical type. - QualType withConst() const { - return Stored.withConst(); - } - - /// \brief Determines whether this canonical type is more qualified than - /// the @p Other canonical type. - bool isMoreQualifiedThan(CanQual<T> Other) const { - return Stored.isMoreQualifiedThan(Other.Stored); - } - - /// \brief Determines whether this canonical type is at least as qualified as - /// the @p Other canonical type. - bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { - return Stored.isAtLeastAsQualifiedAs(Other.Stored); - } - - /// \brief If the canonical type is a reference type, returns the type that - /// it refers to; otherwise, returns the type itself. - CanQual<Type> getNonReferenceType() const; - - /// \brief Retrieve the internal representation of this canonical type. - void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } - - /// \brief Construct a canonical type from its internal representation. - static CanQual<T> getFromOpaquePtr(void *Ptr); - - /// \brief Builds a canonical type from a QualType. - /// - /// This routine is inherently unsafe, because it requires the user to - /// ensure that the given type is a canonical type with the correct - // (dynamic) type. - static CanQual<T> CreateUnsafe(QualType Other); - - void dump() const { Stored.dump(); } - - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddPointer(getAsOpaquePtr()); - } -}; - -template<typename T, typename U> -inline bool operator==(CanQual<T> x, CanQual<U> y) { - return x.getAsOpaquePtr() == y.getAsOpaquePtr(); -} - -template<typename T, typename U> -inline bool operator!=(CanQual<T> x, CanQual<U> y) { - return x.getAsOpaquePtr() != y.getAsOpaquePtr(); -} - -/// \brief Represents a canonical, potentially-qualified type. -typedef CanQual<Type> CanQualType; - -inline CanQualType Type::getCanonicalTypeUnqualified() const { - return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); -} - -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - CanQualType T) { - DB << static_cast<QualType>(T); - return DB; -} - -//----------------------------------------------------------------------------// -// Internal proxy classes used by canonical types -//----------------------------------------------------------------------------// - -#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ -CanQualType Accessor() const { \ -return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ -} - -#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ -Type Accessor() const { return this->getTypePtr()->Accessor(); } - -/// \brief Base class of all canonical proxy types, which is responsible for -/// storing the underlying canonical type and providing basic conversions. -template<typename T> -class CanProxyBase { -protected: - CanQual<T> Stored; - -public: - /// \brief Retrieve the pointer to the underlying Type - const T *getTypePtr() const { return Stored.getTypePtr(); } - - /// \brief Implicit conversion to the underlying pointer. - /// - /// Also provides the ability to use canonical type proxies in a Boolean - // context,e.g., - /// @code - /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } - /// @endcode - operator const T*() const { return this->Stored.getTypePtrOrNull(); } - - /// \brief Try to convert the given canonical type to a specific structural - /// type. - template<typename U> CanProxy<U> getAs() const { - return this->Stored.template getAs<U>(); - } - - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) - - // Type predicates - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) - - /// \brief Retrieve the proxy-adaptor type. - /// - /// This arrow operator is used when CanProxyAdaptor has been specialized - /// for the given type T. In that case, we reference members of the - /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden - /// by the arrow operator in the primary CanProxyAdaptor template. - const CanProxyAdaptor<T> *operator->() const { - return static_cast<const CanProxyAdaptor<T> *>(this); - } -}; - -/// \brief Replacable canonical proxy adaptor class that provides the link -/// between a canonical type and the accessors of the type. -/// -/// The CanProxyAdaptor is a replaceable class template that is instantiated -/// as part of each canonical proxy type. The primary template merely provides -/// redirection to the underlying type (T), e.g., @c PointerType. One can -/// provide specializations of this class template for each underlying type -/// that provide accessors returning canonical types (@c CanQualType) rather -/// than the more typical @c QualType, to propagate the notion of "canonical" -/// through the system. -template<typename T> -struct CanProxyAdaptor : CanProxyBase<T> { }; - -/// \brief Canonical proxy type returned when retrieving the members of a -/// canonical type or as the result of the @c CanQual<T>::getAs member -/// function. -/// -/// The CanProxy type mainly exists as a proxy through which operator-> will -/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy -/// type that provides canonical-type access to the fields of the type. -template<typename T> -class CanProxy : public CanProxyAdaptor<T> { -public: - /// \brief Build a NULL proxy. - CanProxy() { } - - /// \brief Build a proxy to the given canonical type. - CanProxy(CanQual<T> Stored) { this->Stored = Stored; } - - /// \brief Implicit conversion to the stored canonical type. - operator CanQual<T>() const { return this->Stored; } -}; - -} // end namespace clang - -namespace llvm { - -/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from -/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. -/// to return smart pointer (proxies?). -template<typename T> -struct simplify_type< ::clang::CanQual<T> > { - typedef const T *SimpleType; - static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { - return Val.getTypePtr(); - } -}; - -// Teach SmallPtrSet that CanQual<T> is "basically a pointer". -template<typename T> -class PointerLikeTypeTraits<clang::CanQual<T> > { -public: - static inline void *getAsVoidPointer(clang::CanQual<T> P) { - return P.getAsOpaquePtr(); - } - static inline clang::CanQual<T> getFromVoidPointer(void *P) { - return clang::CanQual<T>::getFromOpaquePtr(P); - } - // qualifier information is encoded in the low bits. - enum { NumLowBitsAvailable = 0 }; -}; - -} // end namespace llvm - -namespace clang { - -//----------------------------------------------------------------------------// -// Canonical proxy adaptors for canonical type nodes. -//----------------------------------------------------------------------------// - -/// \brief Iterator adaptor that turns an iterator over canonical QualTypes -/// into an iterator over CanQualTypes. -template <typename InputIterator> -struct CanTypeIterator - : llvm::iterator_adaptor_base< - CanTypeIterator<InputIterator>, InputIterator, - typename std::iterator_traits<InputIterator>::iterator_category, - CanQualType, - typename std::iterator_traits<InputIterator>::difference_type, - CanProxy<Type>, CanQualType> { - CanTypeIterator() {} - explicit CanTypeIterator(InputIterator Iter) - : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} - - CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); } - CanProxy<Type> operator->() const; -}; - -template<> -struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) -}; - -template<> -struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) -}; - -template<> -struct CanProxyAdaptor<BlockPointerType> - : public CanProxyBase<BlockPointerType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) -}; - -template<> -struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) -}; - -template<> -struct CanProxyAdaptor<LValueReferenceType> - : public CanProxyBase<LValueReferenceType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) -}; - -template<> -struct CanProxyAdaptor<RValueReferenceType> - : public CanProxyBase<RValueReferenceType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) -}; - -template<> -struct CanProxyAdaptor<MemberPointerType> - : public CanProxyBase<MemberPointerType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) -}; - -// CanProxyAdaptors for arrays are intentionally unimplemented because -// they are not safe. -template<> struct CanProxyAdaptor<ArrayType>; -template<> struct CanProxyAdaptor<ConstantArrayType>; -template<> struct CanProxyAdaptor<IncompleteArrayType>; -template<> struct CanProxyAdaptor<VariableArrayType>; -template<> struct CanProxyAdaptor<DependentSizedArrayType>; - -template<> -struct CanProxyAdaptor<DependentSizedExtVectorType> - : public CanProxyBase<DependentSizedExtVectorType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) -}; - -template<> -struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) -}; - -template<> -struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) -}; - -template<> -struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) -}; - -template<> -struct CanProxyAdaptor<FunctionNoProtoType> - : public CanProxyBase<FunctionNoProtoType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) -}; - -template<> -struct CanProxyAdaptor<FunctionProtoType> - : public CanProxyBase<FunctionProtoType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) - CanQualType getParamType(unsigned i) const { - return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); - } - - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) - - typedef CanTypeIterator<FunctionProtoType::param_type_iterator> - param_type_iterator; - - param_type_iterator param_type_begin() const { - return param_type_iterator(this->getTypePtr()->param_type_begin()); - } - - param_type_iterator param_type_end() const { - return param_type_iterator(this->getTypePtr()->param_type_end()); - } - - // Note: canonical function types never have exception specifications -}; - -template<> -struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) -}; - -template<> -struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) -}; - -template <> -struct CanProxyAdaptor<UnaryTransformType> - : public CanProxyBase<UnaryTransformType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind) -}; - -template<> -struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) -}; - -template<> -struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) -}; - -template<> -struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) -}; - -template<> -struct CanProxyAdaptor<TemplateTypeParmType> - : public CanProxyBase<TemplateTypeParmType> { - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) -}; - -template<> -struct CanProxyAdaptor<ObjCObjectType> - : public CanProxyBase<ObjCObjectType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, - getInterface) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) - - typedef ObjCObjectPointerType::qual_iterator qual_iterator; - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) -}; - -template<> -struct CanProxyAdaptor<ObjCObjectPointerType> - : public CanProxyBase<ObjCObjectPointerType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, - getInterfaceType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) - - typedef ObjCObjectPointerType::qual_iterator qual_iterator; - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) -}; - -//----------------------------------------------------------------------------// -// Method and function definitions -//----------------------------------------------------------------------------// -template<typename T> -inline CanQual<T> CanQual<T>::getUnqualifiedType() const { - return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); -} - -template<typename T> -inline CanQual<Type> CanQual<T>::getNonReferenceType() const { - if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) - return RefType->getPointeeType(); - else - return *this; -} - -template<typename T> -CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { - CanQual<T> Result; - Result.Stored = QualType::getFromOpaquePtr(Ptr); - assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || - Result.Stored.isCanonical()) && "Type is not canonical!"); - return Result; -} - -template<typename T> -CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { - assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); - assert((Other.isNull() || isa<T>(Other.getTypePtr())) && - "Dynamic type does not meet the static type's requires"); - CanQual<T> Result; - Result.Stored = Other; - return Result; -} - -template<typename T> -template<typename U> -CanProxy<U> CanQual<T>::getAs() const { - ArrayType_cannot_be_used_with_getAs<U> at; - (void)at; - - if (Stored.isNull()) - return CanProxy<U>(); - - if (isa<U>(Stored.getTypePtr())) - return CanQual<U>::CreateUnsafe(Stored); - - return CanProxy<U>(); -} - -template<typename T> -template<typename U> -CanProxy<U> CanQual<T>::castAs() const { - ArrayType_cannot_be_used_with_getAs<U> at; - (void)at; - - assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); - return CanQual<U>::CreateUnsafe(Stored); -} - -template<typename T> -CanProxy<T> CanQual<T>::operator->() const { - return CanProxy<T>(*this); -} - -template <typename InputIterator> -CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { - return CanProxy<Type>(*this); -} - -} - - -#endif diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h deleted file mode 100644 index 1d22bcc..0000000 --- a/include/clang/AST/CharUnits.h +++ /dev/null @@ -1,240 +0,0 @@ -//===--- CharUnits.h - Character units for sizes and offsets ----*- 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 CharUnits class -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_CHARUNITS_H -#define LLVM_CLANG_AST_CHARUNITS_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/MathExtras.h" - -namespace clang { - - /// CharUnits - This is an opaque type for sizes expressed in character units. - /// Instances of this type represent a quantity as a multiple of the size - /// of the standard C type, char, on the target architecture. As an opaque - /// type, CharUnits protects you from accidentally combining operations on - /// quantities in bit units and character units. - /// - /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned - /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to - /// the same quantity of storage. However, we use the term 'character unit' - /// rather than 'byte' to avoid an implication that a character unit is - /// exactly 8 bits. - /// - /// For portability, never assume that a target character is 8 bits wide. Use - /// CharUnit values wherever you calculate sizes, offsets, or alignments - /// in character units. - class CharUnits { - public: - typedef int64_t QuantityType; - - private: - QuantityType Quantity; - - explicit CharUnits(QuantityType C) : Quantity(C) {} - - public: - - /// CharUnits - A default constructor. - CharUnits() : Quantity(0) {} - - /// Zero - Construct a CharUnits quantity of zero. - static CharUnits Zero() { - return CharUnits(0); - } - - /// One - Construct a CharUnits quantity of one. - static CharUnits One() { - return CharUnits(1); - } - - /// fromQuantity - Construct a CharUnits quantity from a raw integer type. - static CharUnits fromQuantity(QuantityType Quantity) { - return CharUnits(Quantity); - } - - // Compound assignment. - CharUnits& operator+= (const CharUnits &Other) { - Quantity += Other.Quantity; - return *this; - } - CharUnits& operator++ () { - ++Quantity; - return *this; - } - CharUnits operator++ (int) { - return CharUnits(Quantity++); - } - CharUnits& operator-= (const CharUnits &Other) { - Quantity -= Other.Quantity; - return *this; - } - CharUnits& operator-- () { - --Quantity; - return *this; - } - CharUnits operator-- (int) { - return CharUnits(Quantity--); - } - - // Comparison operators. - bool operator== (const CharUnits &Other) const { - return Quantity == Other.Quantity; - } - bool operator!= (const CharUnits &Other) const { - return Quantity != Other.Quantity; - } - - // Relational operators. - bool operator< (const CharUnits &Other) const { - return Quantity < Other.Quantity; - } - bool operator<= (const CharUnits &Other) const { - return Quantity <= Other.Quantity; - } - bool operator> (const CharUnits &Other) const { - return Quantity > Other.Quantity; - } - bool operator>= (const CharUnits &Other) const { - return Quantity >= Other.Quantity; - } - - // Other predicates. - - /// isZero - Test whether the quantity equals zero. - bool isZero() const { return Quantity == 0; } - - /// isOne - Test whether the quantity equals one. - bool isOne() const { return Quantity == 1; } - - /// isPositive - Test whether the quantity is greater than zero. - bool isPositive() const { return Quantity > 0; } - - /// isNegative - Test whether the quantity is less than zero. - bool isNegative() const { return Quantity < 0; } - - /// isPowerOfTwo - Test whether the quantity is a power of two. - /// Zero is not a power of two. - bool isPowerOfTwo() const { - return (Quantity & -Quantity) == Quantity; - } - - /// Test whether this is a multiple of the other value. - /// - /// Among other things, this promises that - /// self.RoundUpToAlignment(N) will just return self. - bool isMultipleOf(CharUnits N) const { - return (*this % N) == 0; - } - - // Arithmetic operators. - CharUnits operator* (QuantityType N) const { - return CharUnits(Quantity * N); - } - CharUnits operator/ (QuantityType N) const { - return CharUnits(Quantity / N); - } - QuantityType operator/ (const CharUnits &Other) const { - return Quantity / Other.Quantity; - } - CharUnits operator% (QuantityType N) const { - return CharUnits(Quantity % N); - } - QuantityType operator% (const CharUnits &Other) const { - return Quantity % Other.Quantity; - } - CharUnits operator+ (const CharUnits &Other) const { - return CharUnits(Quantity + Other.Quantity); - } - 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 \p Align. - /// Align must be non-zero. - CharUnits RoundUpToAlignment(const CharUnits &Align) const { - return CharUnits(llvm::RoundUpToAlignment(Quantity, - Align.Quantity)); - } - - /// Given that this is a non-zero alignment value, what is the - /// alignment at the given offset? - CharUnits alignmentAtOffset(CharUnits offset) const { - assert(Quantity != 0 && "offsetting from unknown alignment?"); - return CharUnits(llvm::MinAlign(Quantity, offset.Quantity)); - } - - /// Given that this is the alignment of the first element of an - /// array, return the minimum alignment of any element in the array. - CharUnits alignmentOfArrayElement(CharUnits elementSize) const { - // Since we don't track offsetted alignments, the alignment of - // the second element (or any odd element) will be minimally - // aligned. - return alignmentAtOffset(elementSize); - } - - - }; // class CharUnit -} // namespace clang - -inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale, - const clang::CharUnits &CU) { - 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/Comment.h b/include/clang/AST/Comment.h deleted file mode 100644 index 94470cb..0000000 --- a/include/clang/AST/Comment.h +++ /dev/null @@ -1,1142 +0,0 @@ -//===--- Comment.h - Comment AST nodes --------------------------*- 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 comment AST nodes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENT_H -#define LLVM_CLANG_AST_COMMENT_H - -#include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Type.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" - -namespace clang { -class Decl; -class ParmVarDecl; -class TemplateParameterList; - -namespace comments { -class FullComment; - -/// Describes the syntax that was used in a documentation command. -/// -/// Exact values of this enumeration are important because they used to select -/// parts of diagnostic messages. Audit diagnostics before changing or adding -/// a new value. -enum CommandMarkerKind { - /// Command started with a backslash character: - /// \code - /// \foo - /// \endcode - CMK_Backslash = 0, - - /// Command started with an 'at' character: - /// \code - /// @foo - /// \endcode - CMK_At = 1 -}; - -/// Any part of the comment. -/// Abstract class. -class Comment { -protected: - /// Preferred location to show caret. - SourceLocation Loc; - - /// Source range of this AST node. - SourceRange Range; - - class CommentBitfields { - friend class Comment; - - /// Type of this AST node. - unsigned Kind : 8; - }; - enum { NumCommentBits = 8 }; - - class InlineContentCommentBitfields { - friend class InlineContentComment; - - unsigned : NumCommentBits; - - /// True if there is a newline after this inline content node. - /// (There is no separate AST node for a newline.) - unsigned HasTrailingNewline : 1; - }; - enum { NumInlineContentCommentBits = NumCommentBits + 1 }; - - class TextCommentBitfields { - friend class TextComment; - - unsigned : NumInlineContentCommentBits; - - /// True if \c IsWhitespace field contains a valid value. - mutable unsigned IsWhitespaceValid : 1; - - /// True if this comment AST node contains only whitespace. - mutable unsigned IsWhitespace : 1; - }; - enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; - - class InlineCommandCommentBitfields { - friend class InlineCommandComment; - - unsigned : NumInlineContentCommentBits; - - unsigned RenderKind : 2; - unsigned CommandID : CommandInfo::NumCommandIDBits; - }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + - CommandInfo::NumCommandIDBits }; - - class HTMLTagCommentBitfields { - friend class HTMLTagComment; - - unsigned : NumInlineContentCommentBits; - - /// True if we found that this tag is malformed in some way. - unsigned IsMalformed : 1; - }; - enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 }; - - class HTMLStartTagCommentBitfields { - friend class HTMLStartTagComment; - - unsigned : NumHTMLTagCommentBits; - - /// True if this tag is self-closing (e. g., <br />). This is based on tag - /// spelling in comment (plain <br> would not set this flag). - unsigned IsSelfClosing : 1; - }; - enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 }; - - class ParagraphCommentBitfields { - friend class ParagraphComment; - - unsigned : NumCommentBits; - - /// True if \c IsWhitespace field contains a valid value. - mutable unsigned IsWhitespaceValid : 1; - - /// True if this comment AST node contains only whitespace. - mutable unsigned IsWhitespace : 1; - }; - enum { NumParagraphCommentBits = NumCommentBits + 2 }; - - class BlockCommandCommentBitfields { - friend class BlockCommandComment; - - unsigned : NumCommentBits; - - unsigned CommandID : CommandInfo::NumCommandIDBits; - - /// Describes the syntax that was used in a documentation command. - /// Contains values from CommandMarkerKind enum. - unsigned CommandMarker : 1; - }; - enum { NumBlockCommandCommentBits = NumCommentBits + - CommandInfo::NumCommandIDBits + 1 }; - - class ParamCommandCommentBitfields { - friend class ParamCommandComment; - - unsigned : NumBlockCommandCommentBits; - - /// Parameter passing direction, see ParamCommandComment::PassDirection. - unsigned Direction : 2; - - /// True if direction was specified explicitly in the comment. - unsigned IsDirectionExplicit : 1; - }; - enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; - - union { - CommentBitfields CommentBits; - InlineContentCommentBitfields InlineContentCommentBits; - TextCommentBitfields TextCommentBits; - InlineCommandCommentBitfields InlineCommandCommentBits; - HTMLTagCommentBitfields HTMLTagCommentBits; - HTMLStartTagCommentBitfields HTMLStartTagCommentBits; - ParagraphCommentBitfields ParagraphCommentBits; - BlockCommandCommentBitfields BlockCommandCommentBits; - ParamCommandCommentBitfields ParamCommandCommentBits; - }; - - void setSourceRange(SourceRange SR) { - Range = SR; - } - - void setLocation(SourceLocation L) { - Loc = L; - } - -public: - enum CommentKind { - NoCommentKind = 0, -#define COMMENT(CLASS, PARENT) CLASS##Kind, -#define COMMENT_RANGE(BASE, FIRST, LAST) \ - First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, -#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ - First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind -#define ABSTRACT_COMMENT(COMMENT) -#include "clang/AST/CommentNodes.inc" - }; - - Comment(CommentKind K, - SourceLocation LocBegin, - SourceLocation LocEnd) : - Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { - CommentBits.Kind = K; - } - - CommentKind getCommentKind() const { - return static_cast<CommentKind>(CommentBits.Kind); - } - - const char *getCommentKindName() const; - - void dump() const; - void dumpColor() const; - void dump(const ASTContext &Context) const; - void dump(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM) const; - - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - - SourceLocation getLocStart() const LLVM_READONLY { - return Range.getBegin(); - } - - SourceLocation getLocEnd() const LLVM_READONLY { - return Range.getEnd(); - } - - SourceLocation getLocation() const LLVM_READONLY { return Loc; } - - typedef Comment * const *child_iterator; - - child_iterator child_begin() const; - child_iterator child_end() const; - - // TODO: const child iterator - - unsigned child_count() const { - return child_end() - child_begin(); - } -}; - -/// Inline content (contained within a block). -/// Abstract class. -class InlineContentComment : public Comment { -protected: - InlineContentComment(CommentKind K, - SourceLocation LocBegin, - SourceLocation LocEnd) : - Comment(K, LocBegin, LocEnd) { - InlineContentCommentBits.HasTrailingNewline = 0; - } - -public: - static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstInlineContentCommentConstant && - C->getCommentKind() <= LastInlineContentCommentConstant; - } - - void addTrailingNewline() { - InlineContentCommentBits.HasTrailingNewline = 1; - } - - bool hasTrailingNewline() const { - return InlineContentCommentBits.HasTrailingNewline; - } -}; - -/// Plain text. -class TextComment : public InlineContentComment { - StringRef Text; - -public: - TextComment(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef Text) : - InlineContentComment(TextCommentKind, LocBegin, LocEnd), - Text(Text) { - TextCommentBits.IsWhitespaceValid = false; - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == TextCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } - - StringRef getText() const LLVM_READONLY { return Text; } - - bool isWhitespace() const { - if (TextCommentBits.IsWhitespaceValid) - return TextCommentBits.IsWhitespace; - - TextCommentBits.IsWhitespace = isWhitespaceNoCache(); - TextCommentBits.IsWhitespaceValid = true; - return TextCommentBits.IsWhitespace; - } - -private: - bool isWhitespaceNoCache() const; -}; - -/// A command with word-like arguments that is considered inline content. -class InlineCommandComment : public InlineContentComment { -public: - struct Argument { - SourceRange Range; - StringRef Text; - - Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } - }; - - /// The most appropriate rendering mode for this command, chosen on command - /// semantics in Doxygen. - enum RenderKind { - RenderNormal, - RenderBold, - RenderMonospaced, - RenderEmphasized - }; - -protected: - /// Command arguments. - ArrayRef<Argument> Args; - -public: - InlineCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - RenderKind RK, - ArrayRef<Argument> Args) : - InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), - Args(Args) { - InlineCommandCommentBits.RenderKind = RK; - InlineCommandCommentBits.CommandID = CommandID; - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == InlineCommandCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } - - unsigned getCommandID() const { - return InlineCommandCommentBits.CommandID; - } - - StringRef getCommandName(const CommandTraits &Traits) const { - return Traits.getCommandInfo(getCommandID())->Name; - } - - SourceRange getCommandNameRange() const { - return SourceRange(getLocStart().getLocWithOffset(-1), - getLocEnd()); - } - - RenderKind getRenderKind() const { - return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); - } - - unsigned getNumArgs() const { - return Args.size(); - } - - StringRef getArgText(unsigned Idx) const { - return Args[Idx].Text; - } - - SourceRange getArgRange(unsigned Idx) const { - return Args[Idx].Range; - } -}; - -/// Abstract class for opening and closing HTML tags. HTML tags are always -/// treated as inline content (regardless HTML semantics). -class HTMLTagComment : public InlineContentComment { -protected: - StringRef TagName; - SourceRange TagNameRange; - - HTMLTagComment(CommentKind K, - SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef TagName, - SourceLocation TagNameBegin, - SourceLocation TagNameEnd) : - InlineContentComment(K, LocBegin, LocEnd), - TagName(TagName), - TagNameRange(TagNameBegin, TagNameEnd) { - setLocation(TagNameBegin); - HTMLTagCommentBits.IsMalformed = 0; - } - -public: - static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstHTMLTagCommentConstant && - C->getCommentKind() <= LastHTMLTagCommentConstant; - } - - StringRef getTagName() const LLVM_READONLY { return TagName; } - - SourceRange getTagNameSourceRange() const LLVM_READONLY { - SourceLocation L = getLocation(); - return SourceRange(L.getLocWithOffset(1), - L.getLocWithOffset(1 + TagName.size())); - } - - bool isMalformed() const { - return HTMLTagCommentBits.IsMalformed; - } - - void setIsMalformed() { - HTMLTagCommentBits.IsMalformed = 1; - } -}; - -/// An opening HTML tag with attributes. -class HTMLStartTagComment : public HTMLTagComment { -public: - class Attribute { - public: - SourceLocation NameLocBegin; - StringRef Name; - - SourceLocation EqualsLoc; - - SourceRange ValueRange; - StringRef Value; - - Attribute() { } - - Attribute(SourceLocation NameLocBegin, StringRef Name) : - NameLocBegin(NameLocBegin), Name(Name), - EqualsLoc(SourceLocation()), - ValueRange(SourceRange()), Value(StringRef()) - { } - - Attribute(SourceLocation NameLocBegin, StringRef Name, - SourceLocation EqualsLoc, - SourceRange ValueRange, StringRef Value) : - NameLocBegin(NameLocBegin), Name(Name), - EqualsLoc(EqualsLoc), - ValueRange(ValueRange), Value(Value) - { } - - SourceLocation getNameLocEnd() const { - return NameLocBegin.getLocWithOffset(Name.size()); - } - - SourceRange getNameRange() const { - return SourceRange(NameLocBegin, getNameLocEnd()); - } - }; - -private: - ArrayRef<Attribute> Attributes; - -public: - HTMLStartTagComment(SourceLocation LocBegin, - StringRef TagName) : - HTMLTagComment(HTMLStartTagCommentKind, - LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), - TagName, - LocBegin.getLocWithOffset(1), - LocBegin.getLocWithOffset(1 + TagName.size())) { - HTMLStartTagCommentBits.IsSelfClosing = false; - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == HTMLStartTagCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } - - unsigned getNumAttrs() const { - return Attributes.size(); - } - - const Attribute &getAttr(unsigned Idx) const { - return Attributes[Idx]; - } - - void setAttrs(ArrayRef<Attribute> Attrs) { - Attributes = Attrs; - if (!Attrs.empty()) { - const Attribute &Attr = Attrs.back(); - SourceLocation L = Attr.ValueRange.getEnd(); - if (L.isValid()) - Range.setEnd(L); - else { - Range.setEnd(Attr.getNameLocEnd()); - } - } - } - - void setGreaterLoc(SourceLocation GreaterLoc) { - Range.setEnd(GreaterLoc); - } - - bool isSelfClosing() const { - return HTMLStartTagCommentBits.IsSelfClosing; - } - - void setSelfClosing() { - HTMLStartTagCommentBits.IsSelfClosing = true; - } -}; - -/// A closing HTML tag. -class HTMLEndTagComment : public HTMLTagComment { -public: - HTMLEndTagComment(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef TagName) : - HTMLTagComment(HTMLEndTagCommentKind, - LocBegin, LocEnd, - TagName, - LocBegin.getLocWithOffset(2), - LocBegin.getLocWithOffset(2 + TagName.size())) - { } - - static bool classof(const Comment *C) { - return C->getCommentKind() == HTMLEndTagCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } -}; - -/// Block content (contains inline content). -/// Abstract class. -class BlockContentComment : public Comment { -protected: - BlockContentComment(CommentKind K, - SourceLocation LocBegin, - SourceLocation LocEnd) : - Comment(K, LocBegin, LocEnd) - { } - -public: - static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstBlockContentCommentConstant && - C->getCommentKind() <= LastBlockContentCommentConstant; - } -}; - -/// A single paragraph that contains inline content. -class ParagraphComment : public BlockContentComment { - ArrayRef<InlineContentComment *> Content; - -public: - ParagraphComment(ArrayRef<InlineContentComment *> Content) : - BlockContentComment(ParagraphCommentKind, - SourceLocation(), - SourceLocation()), - Content(Content) { - if (Content.empty()) { - ParagraphCommentBits.IsWhitespace = true; - ParagraphCommentBits.IsWhitespaceValid = true; - return; - } - - ParagraphCommentBits.IsWhitespaceValid = false; - - setSourceRange(SourceRange(Content.front()->getLocStart(), - Content.back()->getLocEnd())); - setLocation(Content.front()->getLocStart()); - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == ParagraphCommentKind; - } - - child_iterator child_begin() const { - return reinterpret_cast<child_iterator>(Content.begin()); - } - - child_iterator child_end() const { - return reinterpret_cast<child_iterator>(Content.end()); - } - - bool isWhitespace() const { - if (ParagraphCommentBits.IsWhitespaceValid) - return ParagraphCommentBits.IsWhitespace; - - ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); - ParagraphCommentBits.IsWhitespaceValid = true; - return ParagraphCommentBits.IsWhitespace; - } - -private: - bool isWhitespaceNoCache() const; -}; - -/// A command that has zero or more word-like arguments (number of word-like -/// arguments depends on command name) and a paragraph as an argument -/// (e. g., \\brief). -class BlockCommandComment : public BlockContentComment { -public: - struct Argument { - SourceRange Range; - StringRef Text; - - Argument() { } - Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } - }; - -protected: - /// Word-like arguments. - ArrayRef<Argument> Args; - - /// Paragraph argument. - ParagraphComment *Paragraph; - - BlockCommandComment(CommentKind K, - SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockContentComment(K, LocBegin, LocEnd), - Paragraph(nullptr) { - setLocation(getCommandNameBeginLoc()); - BlockCommandCommentBits.CommandID = CommandID; - BlockCommandCommentBits.CommandMarker = CommandMarker; - } - -public: - BlockCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Paragraph(nullptr) { - setLocation(getCommandNameBeginLoc()); - BlockCommandCommentBits.CommandID = CommandID; - BlockCommandCommentBits.CommandMarker = CommandMarker; - } - - static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstBlockCommandCommentConstant && - C->getCommentKind() <= LastBlockCommandCommentConstant; - } - - child_iterator child_begin() const { - return reinterpret_cast<child_iterator>(&Paragraph); - } - - child_iterator child_end() const { - return reinterpret_cast<child_iterator>(&Paragraph + 1); - } - - unsigned getCommandID() const { - return BlockCommandCommentBits.CommandID; - } - - StringRef getCommandName(const CommandTraits &Traits) const { - return Traits.getCommandInfo(getCommandID())->Name; - } - - SourceLocation getCommandNameBeginLoc() const { - return getLocStart().getLocWithOffset(1); - } - - SourceRange getCommandNameRange(const CommandTraits &Traits) const { - StringRef Name = getCommandName(Traits); - return SourceRange(getCommandNameBeginLoc(), - getLocStart().getLocWithOffset(1 + Name.size())); - } - - unsigned getNumArgs() const { - return Args.size(); - } - - StringRef getArgText(unsigned Idx) const { - return Args[Idx].Text; - } - - SourceRange getArgRange(unsigned Idx) const { - return Args[Idx].Range; - } - - void setArgs(ArrayRef<Argument> A) { - Args = A; - if (Args.size() > 0) { - SourceLocation NewLocEnd = Args.back().Range.getEnd(); - if (NewLocEnd.isValid()) - setSourceRange(SourceRange(getLocStart(), NewLocEnd)); - } - } - - ParagraphComment *getParagraph() const LLVM_READONLY { - return Paragraph; - } - - bool hasNonWhitespaceParagraph() const { - return Paragraph && !Paragraph->isWhitespace(); - } - - void setParagraph(ParagraphComment *PC) { - Paragraph = PC; - SourceLocation NewLocEnd = PC->getLocEnd(); - if (NewLocEnd.isValid()) - setSourceRange(SourceRange(getLocStart(), NewLocEnd)); - } - - CommandMarkerKind getCommandMarker() const LLVM_READONLY { - return static_cast<CommandMarkerKind>( - BlockCommandCommentBits.CommandMarker); - } -}; - -/// Doxygen \\param command. -class ParamCommandComment : public BlockCommandComment { -private: - /// Parameter index in the function declaration. - unsigned ParamIndex; - -public: - enum : unsigned { - InvalidParamIndex = ~0U, - VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U - }; - - ParamCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, - CommandID, CommandMarker), - ParamIndex(InvalidParamIndex) { - ParamCommandCommentBits.Direction = In; - ParamCommandCommentBits.IsDirectionExplicit = false; - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == ParamCommandCommentKind; - } - - enum PassDirection { - In, - Out, - InOut - }; - - static const char *getDirectionAsString(PassDirection D); - - PassDirection getDirection() const LLVM_READONLY { - return static_cast<PassDirection>(ParamCommandCommentBits.Direction); - } - - bool isDirectionExplicit() const LLVM_READONLY { - return ParamCommandCommentBits.IsDirectionExplicit; - } - - void setDirection(PassDirection Direction, bool Explicit) { - ParamCommandCommentBits.Direction = Direction; - ParamCommandCommentBits.IsDirectionExplicit = Explicit; - } - - bool hasParamName() const { - return getNumArgs() > 0; - } - - StringRef getParamName(const FullComment *FC) const; - - StringRef getParamNameAsWritten() const { - return Args[0].Text; - } - - SourceRange getParamNameRange() const { - return Args[0].Range; - } - - bool isParamIndexValid() const LLVM_READONLY { - return ParamIndex != InvalidParamIndex; - } - - bool isVarArgParam() const LLVM_READONLY { - return ParamIndex == VarArgParamIndex; - } - - void setIsVarArgParam() { - ParamIndex = VarArgParamIndex; - assert(isParamIndexValid()); - } - - unsigned getParamIndex() const LLVM_READONLY { - assert(isParamIndexValid()); - assert(!isVarArgParam()); - return ParamIndex; - } - - void setParamIndex(unsigned Index) { - ParamIndex = Index; - assert(isParamIndexValid()); - assert(!isVarArgParam()); - } -}; - -/// Doxygen \\tparam command, describes a template parameter. -class TParamCommandComment : public BlockCommandComment { -private: - /// If this template parameter name was resolved (found in template parameter - /// list), then this stores a list of position indexes in all template - /// parameter lists. - /// - /// For example: - /// \verbatim - /// template<typename C, template<typename T> class TT> - /// void test(TT<int> aaa); - /// \endverbatim - /// For C: Position = { 0 } - /// For TT: Position = { 1 } - /// For T: Position = { 1, 0 } - ArrayRef<unsigned> Position; - -public: - TParamCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, - CommandMarker) - { } - - static bool classof(const Comment *C) { - return C->getCommentKind() == TParamCommandCommentKind; - } - - bool hasParamName() const { - return getNumArgs() > 0; - } - - StringRef getParamName(const FullComment *FC) const; - - StringRef getParamNameAsWritten() const { - return Args[0].Text; - } - - SourceRange getParamNameRange() const { - return Args[0].Range; - } - - bool isPositionValid() const LLVM_READONLY { - return !Position.empty(); - } - - unsigned getDepth() const { - assert(isPositionValid()); - return Position.size(); - } - - unsigned getIndex(unsigned Depth) const { - assert(isPositionValid()); - return Position[Depth]; - } - - void setPosition(ArrayRef<unsigned> NewPosition) { - Position = NewPosition; - assert(isPositionValid()); - } -}; - -/// A line of text contained in a verbatim block. -class VerbatimBlockLineComment : public Comment { - StringRef Text; - -public: - VerbatimBlockLineComment(SourceLocation LocBegin, - StringRef Text) : - Comment(VerbatimBlockLineCommentKind, - LocBegin, - LocBegin.getLocWithOffset(Text.size())), - Text(Text) - { } - - static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimBlockLineCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } - - StringRef getText() const LLVM_READONLY { - return Text; - } -}; - -/// A verbatim block command (e. g., preformatted code). Verbatim block has an -/// opening and a closing command and contains multiple lines of text -/// (VerbatimBlockLineComment nodes). -class VerbatimBlockComment : public BlockCommandComment { -protected: - StringRef CloseName; - SourceLocation CloseNameLocBegin; - ArrayRef<VerbatimBlockLineComment *> Lines; - -public: - VerbatimBlockComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID) : - BlockCommandComment(VerbatimBlockCommentKind, - LocBegin, LocEnd, CommandID, - CMK_At) // FIXME: improve source fidelity. - { } - - static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimBlockCommentKind; - } - - child_iterator child_begin() const { - return reinterpret_cast<child_iterator>(Lines.begin()); - } - - child_iterator child_end() const { - return reinterpret_cast<child_iterator>(Lines.end()); - } - - void setCloseName(StringRef Name, SourceLocation LocBegin) { - CloseName = Name; - CloseNameLocBegin = LocBegin; - } - - void setLines(ArrayRef<VerbatimBlockLineComment *> L) { - Lines = L; - } - - StringRef getCloseName() const { - return CloseName; - } - - unsigned getNumLines() const { - return Lines.size(); - } - - StringRef getText(unsigned LineIdx) const { - return Lines[LineIdx]->getText(); - } -}; - -/// A verbatim line command. Verbatim line has an opening command, a single -/// line of text (up to the newline after the opening command) and has no -/// closing command. -class VerbatimLineComment : public BlockCommandComment { -protected: - StringRef Text; - SourceLocation TextBegin; - -public: - VerbatimLineComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - SourceLocation TextBegin, - StringRef Text) : - BlockCommandComment(VerbatimLineCommentKind, - LocBegin, LocEnd, - CommandID, - CMK_At), // FIXME: improve source fidelity. - Text(Text), - TextBegin(TextBegin) - { } - - static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimLineCommentKind; - } - - child_iterator child_begin() const { return nullptr; } - - child_iterator child_end() const { return nullptr; } - - StringRef getText() const { - return Text; - } - - SourceRange getTextRange() const { - return SourceRange(TextBegin, getLocEnd()); - } -}; - -/// Information about the declaration, useful to clients of FullComment. -struct DeclInfo { - /// Declaration the comment is actually attached to (in the source). - /// Should not be NULL. - const Decl *CommentDecl; - - /// CurrentDecl is the declaration with which the FullComment is associated. - /// - /// It can be different from \c CommentDecl. It happens when we we decide - /// that the comment originally attached to \c CommentDecl is fine for - /// \c CurrentDecl too (for example, for a redeclaration or an overrider of - /// \c CommentDecl). - /// - /// The information in the DeclInfo corresponds to CurrentDecl. - const Decl *CurrentDecl; - - /// Parameters that can be referenced by \\param if \c CommentDecl is something - /// that we consider a "function". - ArrayRef<const ParmVarDecl *> ParamVars; - - /// Function return type if \c CommentDecl is something that we consider - /// a "function". - QualType ReturnType; - - /// Template parameters that can be referenced by \\tparam if \c CommentDecl is - /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is - /// true). - const TemplateParameterList *TemplateParameters; - - /// A simplified description of \c CommentDecl kind that should be good enough - /// for documentation rendering purposes. - enum DeclKind { - /// Everything else not explicitly mentioned below. - OtherKind, - - /// Something that we consider a "function": - /// \li function, - /// \li function template, - /// \li function template specialization, - /// \li member function, - /// \li member function template, - /// \li member function template specialization, - /// \li ObjC method, - /// \li a typedef for a function pointer, member function pointer, - /// ObjC block. - FunctionKind, - - /// Something that we consider a "class": - /// \li class/struct, - /// \li class template, - /// \li class template (partial) specialization. - ClassKind, - - /// Something that we consider a "variable": - /// \li namespace scope variables; - /// \li static and non-static class data members; - /// \li enumerators. - VariableKind, - - /// A C++ namespace. - NamespaceKind, - - /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), - /// see \c TypedefNameDecl. - TypedefKind, - - /// An enumeration or scoped enumeration. - EnumKind - }; - - /// What kind of template specialization \c CommentDecl is. - enum TemplateDeclKind { - NotTemplate, - Template, - TemplateSpecialization, - TemplatePartialSpecialization - }; - - /// If false, only \c CommentDecl is valid. - unsigned IsFilled : 1; - - /// Simplified kind of \c CommentDecl, see \c DeclKind enum. - unsigned Kind : 3; - - /// Is \c CommentDecl a template declaration. - unsigned TemplateKind : 2; - - /// Is \c CommentDecl an ObjCMethodDecl. - unsigned IsObjCMethod : 1; - - /// Is \c CommentDecl a non-static member function of C++ class or - /// instance method of ObjC class. - /// Can be true only if \c IsFunctionDecl is true. - unsigned IsInstanceMethod : 1; - - /// Is \c CommentDecl a static member function of C++ class or - /// class method of ObjC class. - /// Can be true only if \c IsFunctionDecl is true. - unsigned IsClassMethod : 1; - - void fill(); - - DeclKind getKind() const LLVM_READONLY { - return static_cast<DeclKind>(Kind); - } - - TemplateDeclKind getTemplateKind() const LLVM_READONLY { - return static_cast<TemplateDeclKind>(TemplateKind); - } -}; - -/// A full comment attached to a declaration, contains block content. -class FullComment : public Comment { - ArrayRef<BlockContentComment *> Blocks; - DeclInfo *ThisDeclInfo; - -public: - FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : - Comment(FullCommentKind, SourceLocation(), SourceLocation()), - Blocks(Blocks), ThisDeclInfo(D) { - if (Blocks.empty()) - return; - - setSourceRange(SourceRange(Blocks.front()->getLocStart(), - Blocks.back()->getLocEnd())); - setLocation(Blocks.front()->getLocStart()); - } - - static bool classof(const Comment *C) { - return C->getCommentKind() == FullCommentKind; - } - - child_iterator child_begin() const { - return reinterpret_cast<child_iterator>(Blocks.begin()); - } - - child_iterator child_end() const { - return reinterpret_cast<child_iterator>(Blocks.end()); - } - - const Decl *getDecl() const LLVM_READONLY { - return ThisDeclInfo->CommentDecl; - } - - const DeclInfo *getDeclInfo() const LLVM_READONLY { - if (!ThisDeclInfo->IsFilled) - ThisDeclInfo->fill(); - return ThisDeclInfo; - } - - ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; } - -}; -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h deleted file mode 100644 index be5b8ee..0000000 --- a/include/clang/AST/CommentBriefParser.h +++ /dev/null @@ -1,55 +0,0 @@ -//===--- CommentBriefParser.h - Dumb comment parser -------------*- 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 a very simple Doxygen comment parser. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H -#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H - -#include "clang/AST/CommentLexer.h" - -namespace clang { -namespace comments { - -/// A very simple comment parser that extracts "a brief description". -/// -/// Due to a variety of comment styles, it considers the following as "a brief -/// description", in order of priority: -/// \li a \\brief or \\short command, -/// \li the first paragraph, -/// \li a \\result or \\return or \\returns paragraph. -class BriefParser { - Lexer &L; - - const CommandTraits &Traits; - - /// Current lookahead token. - Token Tok; - - SourceLocation ConsumeToken() { - SourceLocation Loc = Tok.getLocation(); - L.lex(Tok); - return Loc; - } - -public: - BriefParser(Lexer &L, const CommandTraits &Traits); - - /// Return the best "brief description" we can find. - std::string Parse(); -}; - -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h deleted file mode 100644 index 289f2fd..0000000 --- a/include/clang/AST/CommentCommandTraits.h +++ /dev/null @@ -1,189 +0,0 @@ -//===--- CommentCommandTraits.h - Comment command properties ----*- 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 class that provides information about comment -// commands. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H -#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H - -#include "clang/Basic/CommentOptions.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/ErrorHandling.h" - -namespace clang { -namespace comments { - -/// \brief Information about a single command. -/// -/// When reordering, adding or removing members please update the corresponding -/// TableGen backend. -struct CommandInfo { - unsigned getID() const { - return ID; - } - - const char *Name; - - /// Name of the command that ends the verbatim block. - const char *EndCommandName; - - /// DRY definition of the number of bits used for a command ID. - enum { NumCommandIDBits = 20 }; - - /// The ID of the command. - unsigned ID : NumCommandIDBits; - - /// Number of word-like arguments for a given block command, except for - /// \\param and \\tparam commands -- these have special argument parsers. - unsigned NumArgs : 4; - - /// True if this command is a inline command (of any kind). - unsigned IsInlineCommand : 1; - - /// True if this command is a block command (of any kind). - unsigned IsBlockCommand : 1; - - /// True if this command is introducing a brief documentation - /// paragraph (\\brief or an alias). - unsigned IsBriefCommand : 1; - - /// True if this command is \\returns or an alias. - unsigned IsReturnsCommand : 1; - - /// True if this command is introducing documentation for a function - /// parameter (\\param or an alias). - unsigned IsParamCommand : 1; - - /// True if this command is introducing documentation for - /// a template parameter (\\tparam or an alias). - unsigned IsTParamCommand : 1; - - /// True if this command is \\throws or an alias. - unsigned IsThrowsCommand : 1; - - /// True if this command is \\deprecated or an alias. - unsigned IsDeprecatedCommand : 1; - - /// \brief True if this is a \\headerfile-like command. - unsigned IsHeaderfileCommand : 1; - - /// True if we don't want to warn about this command being passed an empty - /// paragraph. Meaningful only for block commands. - unsigned IsEmptyParagraphAllowed : 1; - - /// \brief True if this command is a verbatim-like block command. - /// - /// A verbatim-like block command eats every character (except line starting - /// decorations) until matching end command is seen or comment end is hit. - unsigned IsVerbatimBlockCommand : 1; - - /// \brief True if this command is an end command for a verbatim-like block. - unsigned IsVerbatimBlockEndCommand : 1; - - /// \brief True if this command is a verbatim line command. - /// - /// A verbatim-like line command eats everything until a newline is seen or - /// comment end is hit. - unsigned IsVerbatimLineCommand : 1; - - /// \brief True if this command contains a declaration for the entity being - /// documented. - /// - /// For example: - /// \code - /// \fn void f(int a); - /// \endcode - unsigned IsDeclarationCommand : 1; - - /// \brief True if verbatim-like line command is a function declaration. - unsigned IsFunctionDeclarationCommand : 1; - - /// \brief True if block command is further describing a container API; such - /// as \@coclass, \@classdesign, etc. - unsigned IsRecordLikeDetailCommand : 1; - - /// \brief True if block command is a container API; such as \@interface. - unsigned IsRecordLikeDeclarationCommand : 1; - - /// \brief True if this command is unknown. This \c CommandInfo object was - /// created during parsing. - unsigned IsUnknownCommand : 1; -}; - -/// This class provides information about commands that can be used -/// in comments. -class CommandTraits { -public: - enum KnownCommandIDs { -#define COMMENT_COMMAND(NAME) KCI_##NAME, -#include "clang/AST/CommentCommandList.inc" -#undef COMMENT_COMMAND - KCI_Last - }; - - CommandTraits(llvm::BumpPtrAllocator &Allocator, - const CommentOptions &CommentOptions); - - void registerCommentOptions(const CommentOptions &CommentOptions); - - /// \returns a CommandInfo object for a given command name or - /// NULL if no CommandInfo object exists for this command. - const CommandInfo *getCommandInfoOrNULL(StringRef Name) const; - - const CommandInfo *getCommandInfo(StringRef Name) const { - if (const CommandInfo *Info = getCommandInfoOrNULL(Name)) - return Info; - llvm_unreachable("the command should be known"); - } - - const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const; - - const CommandInfo *getCommandInfo(unsigned CommandID) const; - - const CommandInfo *registerUnknownCommand(StringRef CommandName); - - const CommandInfo *registerBlockCommand(StringRef CommandName); - - /// \returns a CommandInfo object for a given command name or - /// NULL if \c Name is not a builtin command. - static const CommandInfo *getBuiltinCommandInfo(StringRef Name); - - /// \returns a CommandInfo object for a given command ID or - /// NULL if \c CommandID is not a builtin command. - static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID); - -private: - CommandTraits(const CommandTraits &) = delete; - void operator=(const CommandTraits &) = delete; - - const CommandInfo *getRegisteredCommandInfo(StringRef Name) const; - const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const; - - CommandInfo *createCommandInfoWithName(StringRef CommandName); - - unsigned NextID; - - /// Allocator for CommandInfo objects. - llvm::BumpPtrAllocator &Allocator; - - SmallVector<CommandInfo *, 4> RegisteredCommands; -}; - -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td deleted file mode 100644 index 958ee03..0000000 --- a/include/clang/AST/CommentCommands.td +++ /dev/null @@ -1,241 +0,0 @@ -//===----------------------------------------------------------------------===// -// Define command classes. -//===----------------------------------------------------------------------===// - -class Command<string name> { - string Name = name; - string EndCommandName = ""; - - int NumArgs = 0; - - bit IsInlineCommand = 0; - - bit IsBlockCommand = 0; - bit IsBriefCommand = 0; - bit IsReturnsCommand = 0; - bit IsParamCommand = 0; - bit IsTParamCommand = 0; - bit IsThrowsCommand = 0; - bit IsDeprecatedCommand = 0; - bit IsHeaderfileCommand = 0; - - bit IsEmptyParagraphAllowed = 0; - - bit IsVerbatimBlockCommand = 0; - bit IsVerbatimBlockEndCommand = 0; - bit IsVerbatimLineCommand = 0; - bit IsDeclarationCommand = 0; - bit IsFunctionDeclarationCommand = 0; - bit IsRecordLikeDetailCommand = 0; - bit IsRecordLikeDeclarationCommand = 0; -} - -class InlineCommand<string name> : Command<name> { - let IsInlineCommand = 1; -} - -class BlockCommand<string name> : Command<name> { - let IsBlockCommand = 1; -} - -class RecordLikeDetailCommand<string name> : BlockCommand<name> { - let IsRecordLikeDetailCommand = 1; -} - -class VerbatimBlockCommand<string name> : Command<name> { - let EndCommandName = name; - let IsVerbatimBlockCommand = 1; -} - -multiclass VerbatimBlockCommand<string name, string endCommandName> { - def Begin : Command<name> { - let EndCommandName = endCommandName; - let IsVerbatimBlockCommand = 1; - } - - def End : Command<endCommandName> { - let IsVerbatimBlockEndCommand = 1; - } -} - -class VerbatimLineCommand<string name> : Command<name> { - let IsVerbatimLineCommand = 1; -} - -class DeclarationVerbatimLineCommand<string name> : - VerbatimLineCommand<name> { - let IsDeclarationCommand = 1; -} - -class FunctionDeclarationVerbatimLineCommand<string name> : - DeclarationVerbatimLineCommand<name> { - let IsFunctionDeclarationCommand = 1; -} - -class RecordLikeDeclarationVerbatimLineCommand<string name> : - DeclarationVerbatimLineCommand<name> { - let IsRecordLikeDeclarationCommand = 1; -} - -//===----------------------------------------------------------------------===// -// InlineCommand -//===----------------------------------------------------------------------===// - -def B : InlineCommand<"b">; -def C : InlineCommand<"c">; -def P : InlineCommand<"p">; -def A : InlineCommand<"a">; -def E : InlineCommand<"e">; -def Em : InlineCommand<"em">; - -//===----------------------------------------------------------------------===// -// BlockCommand -//===----------------------------------------------------------------------===// - -def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; } -def Short : BlockCommand<"short"> { let IsBriefCommand = 1; } - -// Opposite of \brief, it is the default in our implementation. -def Details : BlockCommand<"details">; - -def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; } -def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; } -def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; } - -def Param : BlockCommand<"param"> { let IsParamCommand = 1; } - -// Doxygen command for template parameter documentation. -def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; } - -// HeaderDoc command for template parameter documentation. -def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; } - -def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; } -def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; } -def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; } - -def Deprecated : BlockCommand<"deprecated"> { - let IsEmptyParagraphAllowed = 1; - let IsDeprecatedCommand = 1; -} - -def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; } - -// We don't do any additional semantic analysis for the following -// BlockCommands. It might be a good idea to do something extra for them, but -// for now we model them as plain BlockCommands. -def Arg : BlockCommand<"arg">; -def Attention : BlockCommand<"attention">; -def Author : BlockCommand<"author">; -def Authors : BlockCommand<"authors">; -def Bug : BlockCommand<"bug">; -def Copyright : BlockCommand<"copyright">; -def Date : BlockCommand<"date">; -def Invariant : BlockCommand<"invariant">; -def Li : BlockCommand<"li">; -def Note : BlockCommand<"note">; -def Par : BlockCommand<"par">; -def Post : BlockCommand<"post">; -def Pre : BlockCommand<"pre">; -def Remark : BlockCommand<"remark">; -def Remarks : BlockCommand<"remarks">; -def Sa : BlockCommand<"sa">; -def See : BlockCommand<"see">; -def Since : BlockCommand<"since">; -def Todo : BlockCommand<"todo">; -def Version : BlockCommand<"version">; -def Warning : BlockCommand<"warning">; -// HeaderDoc commands -def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; } -def ClassDesign : RecordLikeDetailCommand<"classdesign">; -def CoClass : RecordLikeDetailCommand<"coclass">; -def Dependency : RecordLikeDetailCommand<"dependency">; -def Discussion : BlockCommand<"discussion">; -def Helper : RecordLikeDetailCommand<"helper">; -def HelperClass : RecordLikeDetailCommand<"helperclass">; -def Helps : RecordLikeDetailCommand<"helps">; -def InstanceSize : RecordLikeDetailCommand<"instancesize">; -def Ownership : RecordLikeDetailCommand<"ownership">; -def Performance : RecordLikeDetailCommand<"performance">; -def Security : RecordLikeDetailCommand<"security">; -def SeeAlso : BlockCommand<"seealso">; -def SuperClass : RecordLikeDetailCommand<"superclass">; - -//===----------------------------------------------------------------------===// -// VerbatimBlockCommand -//===----------------------------------------------------------------------===// - -defm Code : VerbatimBlockCommand<"code", "endcode">; -defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">; -defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">; -defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">; -defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">; -defm Manonly : VerbatimBlockCommand<"manonly", "endmanonly">; -defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">; - -defm Dot : VerbatimBlockCommand<"dot", "enddot">; -defm Msc : VerbatimBlockCommand<"msc", "endmsc">; - -// These three commands have special support in CommentLexer to recognize their -// names. -def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula -defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula -defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment - -// HeaderDoc commands -defm Textblock : VerbatimBlockCommand<"textblock", "/textblock">; -defm Link : VerbatimBlockCommand<"link", "/link">; - -//===----------------------------------------------------------------------===// -// VerbatimLineCommand -//===----------------------------------------------------------------------===// - -def Defgroup : VerbatimLineCommand<"defgroup">; -def Ingroup : VerbatimLineCommand<"ingroup">; -def Addtogroup : VerbatimLineCommand<"addtogroup">; -def Weakgroup : VerbatimLineCommand<"weakgroup">; -def Name : VerbatimLineCommand<"name">; - -def Section : VerbatimLineCommand<"section">; -def Subsection : VerbatimLineCommand<"subsection">; -def Subsubsection : VerbatimLineCommand<"subsubsection">; -def Paragraph : VerbatimLineCommand<"paragraph">; - -def Mainpage : VerbatimLineCommand<"mainpage">; -def Subpage : VerbatimLineCommand<"subpage">; -def Ref : VerbatimLineCommand<"ref">; - -def Relates : VerbatimLineCommand<"relates">; -def Related : VerbatimLineCommand<"related">; -def RelatesAlso : VerbatimLineCommand<"relatesalso">; -def RelatedAlso : VerbatimLineCommand<"relatedalso">; - -//===----------------------------------------------------------------------===// -// DeclarationVerbatimLineCommand -//===----------------------------------------------------------------------===// - -// Doxygen commands. -def Def : DeclarationVerbatimLineCommand<"def">; -def Fn : DeclarationVerbatimLineCommand<"fn">; -def Namespace : DeclarationVerbatimLineCommand<"namespace">; -def Overload : DeclarationVerbatimLineCommand<"overload">; -def Property : DeclarationVerbatimLineCommand<"property">; -def Typedef : DeclarationVerbatimLineCommand<"typedef">; -def Var : DeclarationVerbatimLineCommand<"var">; - -// HeaderDoc commands. -def Class : RecordLikeDeclarationVerbatimLineCommand<"class">; -def Interface : RecordLikeDeclarationVerbatimLineCommand<"interface">; -def Protocol : RecordLikeDeclarationVerbatimLineCommand<"protocol">; -def Struct : RecordLikeDeclarationVerbatimLineCommand<"struct">; -def Union : RecordLikeDeclarationVerbatimLineCommand<"union">; -def Category : DeclarationVerbatimLineCommand<"category">; -def Template : DeclarationVerbatimLineCommand<"template">; -def Function : FunctionDeclarationVerbatimLineCommand<"function">; -def FunctionGroup : FunctionDeclarationVerbatimLineCommand<"functiongroup">; -def Method : FunctionDeclarationVerbatimLineCommand<"method">; -def MethodGroup : FunctionDeclarationVerbatimLineCommand<"methodgroup">; -def Callback : FunctionDeclarationVerbatimLineCommand<"callback">; -def Const : DeclarationVerbatimLineCommand<"const">; -def Constant : DeclarationVerbatimLineCommand<"constant">; -def Enum : DeclarationVerbatimLineCommand<"enum">; diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h deleted file mode 100644 index f3a209b..0000000 --- a/include/clang/AST/CommentDiagnostic.h +++ /dev/null @@ -1,29 +0,0 @@ -//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H -#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H - -#include "clang/Basic/Diagnostic.h" - -namespace clang { - namespace diag { - enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, -#define COMMENTSTART -#include "clang/Basic/DiagnosticCommentKinds.inc" -#undef DIAG - NUM_BUILTIN_COMMENT_DIAGNOSTICS - }; - } // end namespace diag -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentHTMLNamedCharacterReferences.td b/include/clang/AST/CommentHTMLNamedCharacterReferences.td deleted file mode 100644 index 4493108..0000000 --- a/include/clang/AST/CommentHTMLNamedCharacterReferences.td +++ /dev/null @@ -1,177 +0,0 @@ -// HTML Named Character Reference -class NCR<string spelling, int codePoint> { - string Spelling = spelling; - int CodePoint = codePoint; -} - -// The list below includes named character references supported by Doxygen: -// http://www.stack.nl/~dimitri/doxygen/manual/htmlcmds.html -// -// It does not include all HTML 5 named character references. -// -// Corresponding code point values can be found here: -// http://www.w3.org/TR/2011/WD-html5-20110113/named-character-references.html - -def : NCR<"copy", 0x000A9>; -def : NCR<"COPY", 0x000A9>; -def : NCR<"trade", 0x02122>; -def : NCR<"TRADE", 0x02122>; -def : NCR<"reg", 0x000AE>; -def : NCR<"REG", 0x000AE>; -def : NCR<"lt", 0x0003C>; -def : NCR<"Lt", 0x0003C>; -def : NCR<"LT", 0x0003C>; -def : NCR<"gt", 0x0003E>; -def : NCR<"Gt", 0x0003E>; -def : NCR<"GT", 0x0003E>; -def : NCR<"amp", 0x00026>; -def : NCR<"AMP", 0x00026>; -def : NCR<"apos", 0x00027>; -def : NCR<"quot", 0x00022>; -def : NCR<"QUOT", 0x00022>; -def : NCR<"lsquo", 0x02018>; -def : NCR<"rsquo", 0x02019>; -def : NCR<"ldquo", 0x0201C>; -def : NCR<"rdquo", 0x0201D>; -def : NCR<"ndash", 0x02013>; -def : NCR<"mdash", 0x02014>; - -def : NCR<"Auml", 0x000C4>; -def : NCR<"Euml", 0x000CB>; -def : NCR<"Iuml", 0x000CF>; -def : NCR<"Ouml", 0x000D6>; -def : NCR<"Uuml", 0x000DC>; -def : NCR<"Yuml", 0x00178>; -def : NCR<"auml", 0x000E4>; -def : NCR<"euml", 0x000EB>; -def : NCR<"iuml", 0x000EF>; -def : NCR<"ouml", 0x000F6>; -def : NCR<"uuml", 0x000FC>; -def : NCR<"yuml", 0x000FF>; - -def : NCR<"Aacute", 0x000C1>; -def : NCR<"Eacute", 0x000C9>; -def : NCR<"Iacute", 0x000CD>; -def : NCR<"Oacute", 0x000D3>; -def : NCR<"Uacute", 0x000DA>; -def : NCR<"Yacute", 0x000DD>; -def : NCR<"aacute", 0x000E1>; -def : NCR<"eacute", 0x000E9>; -def : NCR<"iacute", 0x000ED>; -def : NCR<"oacute", 0x000F3>; -def : NCR<"uacute", 0x000FA>; -def : NCR<"yacute", 0x000FD>; - -def : NCR<"Agrave", 0x000C0>; -def : NCR<"Egrave", 0x000C8>; -def : NCR<"Igrave", 0x000CC>; -def : NCR<"Ograve", 0x000D2>; -def : NCR<"Ugrave", 0x000D9>; -// def : NCR<"Ygrave", 0x01EF2>; // Defined neither in Doxygen, nor in HTML5. -def : NCR<"agrave", 0x000E0>; -def : NCR<"egrave", 0x000E8>; -def : NCR<"igrave", 0x000EC>; -def : NCR<"ograve", 0x000F2>; -def : NCR<"ugrave", 0x000F9>; -def : NCR<"ygrave", 0x01EF3>; // Defined in Doxygen, not defined in HTML5. - -def : NCR<"Acirc", 0x000C2>; -def : NCR<"Ecirc", 0x000CA>; -def : NCR<"Icirc", 0x000CE>; -def : NCR<"Ocirc", 0x000D4>; -def : NCR<"Ucirc", 0x000DB>; -def : NCR<"Ycirc", 0x00176>; // Not defined in Doxygen, defined in HTML5. -def : NCR<"acirc", 0x000E2>; -def : NCR<"ecirc", 0x000EA>; -def : NCR<"icirc", 0x000EE>; -def : NCR<"ocirc", 0x000F4>; -def : NCR<"ucirc", 0x000FB>; -def : NCR<"ycirc", 0x00177>; - -def : NCR<"Atilde", 0x000C3>; -def : NCR<"Ntilde", 0x000D1>; -def : NCR<"Otilde", 0x000D5>; -def : NCR<"atilde", 0x000E3>; -def : NCR<"ntilde", 0x000F1>; -def : NCR<"otilde", 0x000F5>; - -def : NCR<"szlig", 0x000DF>; - -def : NCR<"ccedil", 0x000E7>; -def : NCR<"Ccedil", 0x000C7>; - -def : NCR<"aring", 0x000E5>; -def : NCR<"Aring", 0x000C5>; - -def : NCR<"nbsp", 0x000A0>; - -def : NCR<"Gamma", 0x00393>; -def : NCR<"Delta", 0x00394>; -def : NCR<"Theta", 0x00398>; -def : NCR<"Lambda", 0x0039B>; -def : NCR<"Xi", 0x0039E>; -def : NCR<"Pi", 0x003A0>; -def : NCR<"Sigma", 0x003A3>; -def : NCR<"Upsilon", 0x003A5>; -def : NCR<"Phi", 0x003A6>; -def : NCR<"Psi", 0x003A8>; -def : NCR<"Omega", 0x003A9>; - -def : NCR<"alpha", 0x003B1>; -def : NCR<"beta", 0x003B2>; -def : NCR<"gamma", 0x003B3>; -def : NCR<"delta", 0x003B4>; -def : NCR<"epsilon", 0x003B5>; -def : NCR<"zeta", 0x003B6>; -def : NCR<"eta", 0x003B7>; -def : NCR<"theta", 0x003B8>; -def : NCR<"iota", 0x003B9>; -def : NCR<"kappa", 0x003BA>; -def : NCR<"lambda", 0x003BB>; -def : NCR<"mu", 0x003BC>; -def : NCR<"nu", 0x003BD>; -def : NCR<"xi", 0x003BE>; -def : NCR<"pi", 0x003C0>; -def : NCR<"rho", 0x003C1>; -def : NCR<"sigma", 0x003C3>; -def : NCR<"tau", 0x003C4>; -def : NCR<"upsilon", 0x003C5>; -def : NCR<"phi", 0x003C6>; -def : NCR<"chi", 0x003C7>; -def : NCR<"psi", 0x003C8>; -def : NCR<"omega", 0x003C9>; -def : NCR<"sigmaf", 0x003C2>; - -def : NCR<"sect", 0x000A7>; -def : NCR<"deg", 0x000B0>; -def : NCR<"prime", 0x02032>; -def : NCR<"Prime", 0x02033>; -def : NCR<"infin", 0x0221E>; -def : NCR<"empty", 0x02205>; -def : NCR<"plusmn", 0x000B1>; -def : NCR<"times", 0x000D7>; -def : NCR<"minus", 0x02212>; -def : NCR<"sdot", 0x022C5>; -def : NCR<"part", 0x02202>; -def : NCR<"nabla", 0x02207>; -def : NCR<"radic", 0x0221A>; -def : NCR<"perp", 0x022A5>; -def : NCR<"sum", 0x02211>; -def : NCR<"int", 0x0222B>; -def : NCR<"prod", 0x0220F>; -def : NCR<"sim", 0x0223C>; -def : NCR<"asymp", 0x02248>; -def : NCR<"ne", 0x02260>; -def : NCR<"equiv", 0x02261>; -def : NCR<"prop", 0x0221D>; -def : NCR<"le", 0x02264>; -def : NCR<"ge", 0x02265>; -def : NCR<"larr", 0x02190>; -def : NCR<"rarr", 0x02192>; -def : NCR<"isin", 0x02208>; -def : NCR<"notin", 0x02209>; -def : NCR<"lceil", 0x02308>; -def : NCR<"rceil", 0x02309>; -def : NCR<"lfloor", 0x0230A>; -def : NCR<"rfloor", 0x0230B>; - diff --git a/include/clang/AST/CommentHTMLTags.td b/include/clang/AST/CommentHTMLTags.td deleted file mode 100644 index 2514900..0000000 --- a/include/clang/AST/CommentHTMLTags.td +++ /dev/null @@ -1,67 +0,0 @@ -class Tag<string spelling> { - string Spelling = spelling; - bit EndTagOptional = 0; - bit EndTagForbidden = 0; -} - -def Em : Tag<"em">; -def Strong : Tag<"strong">; -def Tt : Tag<"tt">; -def I : Tag<"i">; -def B : Tag<"b">; -def Big : Tag<"big">; -def Small : Tag<"small">; -def Strike : Tag<"strike">; -def S : Tag<"s">; -def U : Tag<"u">; -def Font : Tag<"font">; -def A : Tag<"a">; -def Hr : Tag<"hr"> { let EndTagForbidden = 1; } -def Div : Tag<"div">; -def Span : Tag<"span">; -def H1 : Tag<"h1">; -def H2 : Tag<"h2">; -def H3 : Tag<"h3">; -def H4 : Tag<"h4">; -def H5 : Tag<"h5">; -def H6 : Tag<"h6">; -def Code : Tag<"code">; -def Blockquote : Tag<"blockquote">; -def Sub : Tag<"sub">; -def Sup : Tag<"sup">; -def Img : Tag<"img"> { let EndTagForbidden = 1; } -def P : Tag<"p"> { let EndTagOptional = 1; } -def Br : Tag<"br"> { let EndTagForbidden = 1; } -def Pre : Tag<"pre">; -def Ins : Tag<"ins">; -def Del : Tag<"del">; -def Ul : Tag<"ul">; -def Ol : Tag<"ol">; -def Li : Tag<"li"> { let EndTagOptional = 1; } -def Dl : Tag<"dl">; -def Dt : Tag<"dt"> { let EndTagOptional = 1; } -def Dd : Tag<"dd"> { let EndTagOptional = 1; } -def Table : Tag<"table">; -def Caption : Tag<"caption">; -def Thead : Tag<"thead"> { let EndTagOptional = 1; } -def Tfoot : Tag<"tfoot"> { let EndTagOptional = 1; } -def Tbody : Tag<"tbody"> { let EndTagOptional = 1; } -def Colgroup : Tag<"colgroup"> { let EndTagOptional = 1; } -def Col : Tag<"col"> { let EndTagForbidden = 1; } -def Tr : Tag<"tr"> { let EndTagOptional = 1; } -def Th : Tag<"th"> { let EndTagOptional = 1; } -def Td : Tag<"td"> { let EndTagOptional = 1; } - -// Define a blacklist of attributes that are not safe to pass through to HTML -// output if the input is untrusted. -// -// FIXME: this should be a whitelist. When changing this to a whitelist, don't -// forget to change the default in the TableGen backend. -class Attribute<string spelling> { - string Spelling = spelling; - bit IsSafeToPassThrough = 1; -} -class EventHandlerContentAttribute<string spelling> : Attribute<spelling> { - let IsSafeToPassThrough = 0; -} - diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h deleted file mode 100644 index f190b93..0000000 --- a/include/clang/AST/CommentLexer.h +++ /dev/null @@ -1,362 +0,0 @@ -//===--- CommentLexer.h - Lexer for structured comments ---------*- 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 lexer for structured comments and supporting token class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENTLEXER_H -#define LLVM_CLANG_AST_COMMENTLEXER_H - -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { -namespace comments { - -class Lexer; -class TextTokenRetokenizer; -struct CommandInfo; -class CommandTraits; - -namespace tok { -enum TokenKind { - eof, - newline, - text, - unknown_command, // Command that does not have an ID. - backslash_command, // Command with an ID, that used backslash marker. - at_command, // Command with an ID, that used 'at' marker. - verbatim_block_begin, - verbatim_block_line, - verbatim_block_end, - verbatim_line_name, - verbatim_line_text, - html_start_tag, // <tag - html_ident, // attr - html_equals, // = - html_quoted_string, // "blah\"blah" or 'blah\'blah' - html_greater, // > - html_slash_greater, // /> - html_end_tag // </tag -}; -} // end namespace tok - -/// \brief Comment token. -class Token { - friend class Lexer; - friend class TextTokenRetokenizer; - - /// The location of the token. - SourceLocation Loc; - - /// The actual kind of the token. - tok::TokenKind Kind; - - /// Length of the token spelling in comment. Can be 0 for synthenized - /// tokens. - unsigned Length; - - /// Contains text value associated with a token. - const char *TextPtr; - - /// Integer value associated with a token. - /// - /// If the token is a konwn command, contains command ID and TextPtr is - /// unused (command spelling can be found with CommandTraits). Otherwise, - /// contains the length of the string that starts at TextPtr. - unsigned IntVal; - -public: - SourceLocation getLocation() const LLVM_READONLY { return Loc; } - void setLocation(SourceLocation SL) { Loc = SL; } - - SourceLocation getEndLocation() const LLVM_READONLY { - if (Length == 0 || Length == 1) - return Loc; - return Loc.getLocWithOffset(Length - 1); - } - - tok::TokenKind getKind() const LLVM_READONLY { return Kind; } - void setKind(tok::TokenKind K) { Kind = K; } - - bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; } - bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; } - - unsigned getLength() const LLVM_READONLY { return Length; } - void setLength(unsigned L) { Length = L; } - - StringRef getText() const LLVM_READONLY { - assert(is(tok::text)); - return StringRef(TextPtr, IntVal); - } - - void setText(StringRef Text) { - assert(is(tok::text)); - TextPtr = Text.data(); - IntVal = Text.size(); - } - - StringRef getUnknownCommandName() const LLVM_READONLY { - assert(is(tok::unknown_command)); - return StringRef(TextPtr, IntVal); - } - - void setUnknownCommandName(StringRef Name) { - assert(is(tok::unknown_command)); - TextPtr = Name.data(); - IntVal = Name.size(); - } - - unsigned getCommandID() const LLVM_READONLY { - assert(is(tok::backslash_command) || is(tok::at_command)); - return IntVal; - } - - void setCommandID(unsigned ID) { - assert(is(tok::backslash_command) || is(tok::at_command)); - IntVal = ID; - } - - unsigned getVerbatimBlockID() const LLVM_READONLY { - assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - return IntVal; - } - - void setVerbatimBlockID(unsigned ID) { - assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - IntVal = ID; - } - - StringRef getVerbatimBlockText() const LLVM_READONLY { - assert(is(tok::verbatim_block_line)); - return StringRef(TextPtr, IntVal); - } - - void setVerbatimBlockText(StringRef Text) { - assert(is(tok::verbatim_block_line)); - TextPtr = Text.data(); - IntVal = Text.size(); - } - - unsigned getVerbatimLineID() const LLVM_READONLY { - assert(is(tok::verbatim_line_name)); - return IntVal; - } - - void setVerbatimLineID(unsigned ID) { - assert(is(tok::verbatim_line_name)); - IntVal = ID; - } - - StringRef getVerbatimLineText() const LLVM_READONLY { - assert(is(tok::verbatim_line_text)); - return StringRef(TextPtr, IntVal); - } - - void setVerbatimLineText(StringRef Text) { - assert(is(tok::verbatim_line_text)); - TextPtr = Text.data(); - IntVal = Text.size(); - } - - StringRef getHTMLTagStartName() const LLVM_READONLY { - assert(is(tok::html_start_tag)); - return StringRef(TextPtr, IntVal); - } - - void setHTMLTagStartName(StringRef Name) { - assert(is(tok::html_start_tag)); - TextPtr = Name.data(); - IntVal = Name.size(); - } - - StringRef getHTMLIdent() const LLVM_READONLY { - assert(is(tok::html_ident)); - return StringRef(TextPtr, IntVal); - } - - void setHTMLIdent(StringRef Name) { - assert(is(tok::html_ident)); - TextPtr = Name.data(); - IntVal = Name.size(); - } - - StringRef getHTMLQuotedString() const LLVM_READONLY { - assert(is(tok::html_quoted_string)); - return StringRef(TextPtr, IntVal); - } - - void setHTMLQuotedString(StringRef Str) { - assert(is(tok::html_quoted_string)); - TextPtr = Str.data(); - IntVal = Str.size(); - } - - StringRef getHTMLTagEndName() const LLVM_READONLY { - assert(is(tok::html_end_tag)); - return StringRef(TextPtr, IntVal); - } - - void setHTMLTagEndName(StringRef Name) { - assert(is(tok::html_end_tag)); - TextPtr = Name.data(); - IntVal = Name.size(); - } - - void dump(const Lexer &L, const SourceManager &SM) const; -}; - -/// \brief Comment lexer. -class Lexer { -private: - Lexer(const Lexer &) = delete; - void operator=(const Lexer &) = delete; - - /// Allocator for strings that are semantic values of tokens and have to be - /// computed (for example, resolved decimal character references). - llvm::BumpPtrAllocator &Allocator; - - DiagnosticsEngine &Diags; - - const CommandTraits &Traits; - - const char *const BufferStart; - const char *const BufferEnd; - SourceLocation FileLoc; - - const char *BufferPtr; - - /// One past end pointer for the current comment. For BCPL comments points - /// to newline or BufferEnd, for C comments points to star in '*/'. - const char *CommentEnd; - - enum LexerCommentState { - LCS_BeforeComment, - LCS_InsideBCPLComment, - LCS_InsideCComment, - LCS_BetweenComments - }; - - /// Low-level lexer state, track if we are inside or outside of comment. - LexerCommentState CommentState; - - enum LexerState { - /// Lexing normal comment text - LS_Normal, - - /// Finished lexing verbatim block beginning command, will lex first body - /// line. - LS_VerbatimBlockFirstLine, - - /// Lexing verbatim block body line-by-line, skipping line-starting - /// decorations. - LS_VerbatimBlockBody, - - /// Finished lexing verbatim line beginning command, will lex text (one - /// line). - LS_VerbatimLineText, - - /// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes. - LS_HTMLStartTag, - - /// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'. - LS_HTMLEndTag - }; - - /// Current lexing mode. - LexerState State; - - /// If State is LS_VerbatimBlock, contains the name of verbatim end - /// command, including command marker. - SmallString<16> VerbatimBlockEndCommandName; - - /// Given a character reference name (e.g., "lt"), return the character that - /// it stands for (e.g., "<"). - StringRef resolveHTMLNamedCharacterReference(StringRef Name) const; - - /// Given a Unicode codepoint as base-10 integer, return the character. - StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const; - - /// Given a Unicode codepoint as base-16 integer, return the character. - StringRef resolveHTMLHexCharacterReference(StringRef Name) const; - - void formTokenWithChars(Token &Result, const char *TokEnd, - tok::TokenKind Kind); - - void formTextToken(Token &Result, const char *TokEnd) { - StringRef Text(BufferPtr, TokEnd - BufferPtr); - formTokenWithChars(Result, TokEnd, tok::text); - Result.setText(Text); - } - - SourceLocation getSourceLocation(const char *Loc) const { - assert(Loc >= BufferStart && Loc <= BufferEnd && - "Location out of range for this buffer!"); - - const unsigned CharNo = Loc - BufferStart; - return FileLoc.getLocWithOffset(CharNo); - } - - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(Loc, DiagID); - } - - /// Eat string matching regexp \code \s*\* \endcode. - void skipLineStartingDecorations(); - - /// Lex stuff inside comments. CommentEnd should be set correctly. - void lexCommentText(Token &T); - - void setupAndLexVerbatimBlock(Token &T, - const char *TextBegin, - char Marker, const CommandInfo *Info); - - void lexVerbatimBlockFirstLine(Token &T); - - void lexVerbatimBlockBody(Token &T); - - void setupAndLexVerbatimLine(Token &T, const char *TextBegin, - const CommandInfo *Info); - - void lexVerbatimLineText(Token &T); - - void lexHTMLCharacterReference(Token &T); - - void setupAndLexHTMLStartTag(Token &T); - - void lexHTMLStartTag(Token &T); - - void setupAndLexHTMLEndTag(Token &T); - - void lexHTMLEndTag(Token &T); - -public: - Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags, - const CommandTraits &Traits, - SourceLocation FileLoc, - const char *BufferStart, const char *BufferEnd); - - void lex(Token &T); - - StringRef getSpelling(const Token &Tok, - const SourceManager &SourceMgr, - bool *Invalid = nullptr) const; -}; - -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h deleted file mode 100644 index fa88628..0000000 --- a/include/clang/AST/CommentParser.h +++ /dev/null @@ -1,123 +0,0 @@ -//===--- CommentParser.h - Doxygen comment parser ---------------*- 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 Doxygen comment parser. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENTPARSER_H -#define LLVM_CLANG_AST_COMMENTPARSER_H - -#include "clang/AST/Comment.h" -#include "clang/AST/CommentLexer.h" -#include "clang/AST/CommentSema.h" -#include "clang/Basic/Diagnostic.h" -#include "llvm/Support/Allocator.h" - -namespace clang { -class SourceManager; - -namespace comments { -class CommandTraits; - -/// Doxygen comment parser. -class Parser { - Parser(const Parser &) = delete; - void operator=(const Parser &) = delete; - - friend class TextTokenRetokenizer; - - Lexer &L; - - Sema &S; - - /// Allocator for anything that goes into AST nodes. - llvm::BumpPtrAllocator &Allocator; - - /// Source manager for the comment being parsed. - const SourceManager &SourceMgr; - - DiagnosticsEngine &Diags; - - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(Loc, DiagID); - } - - const CommandTraits &Traits; - - /// Current lookahead token. We can safely assume that all tokens are from - /// a single source file. - Token Tok; - - /// A stack of additional lookahead tokens. - SmallVector<Token, 8> MoreLATokens; - - void consumeToken() { - if (MoreLATokens.empty()) - L.lex(Tok); - else - Tok = MoreLATokens.pop_back_val(); - } - - void putBack(const Token &OldTok) { - MoreLATokens.push_back(Tok); - Tok = OldTok; - } - - void putBack(ArrayRef<Token> Toks) { - if (Toks.empty()) - return; - - MoreLATokens.push_back(Tok); - MoreLATokens.append(Toks.rbegin(), std::prev(Toks.rend())); - - Tok = Toks[0]; - } - - bool isTokBlockCommand() { - return (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) && - Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand; - } - -public: - Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, - const SourceManager &SourceMgr, DiagnosticsEngine &Diags, - const CommandTraits &Traits); - - /// Parse arguments for \\param command. - void parseParamCommandArgs(ParamCommandComment *PC, - TextTokenRetokenizer &Retokenizer); - - /// Parse arguments for \\tparam command. - void parseTParamCommandArgs(TParamCommandComment *TPC, - TextTokenRetokenizer &Retokenizer); - - void parseBlockCommandArgs(BlockCommandComment *BC, - TextTokenRetokenizer &Retokenizer, - unsigned NumArgs); - - BlockCommandComment *parseBlockCommand(); - InlineCommandComment *parseInlineCommand(); - - HTMLStartTagComment *parseHTMLStartTag(); - HTMLEndTagComment *parseHTMLEndTag(); - - BlockContentComment *parseParagraphOrBlockCommand(); - - VerbatimBlockComment *parseVerbatimBlock(); - VerbatimLineComment *parseVerbatimLine(); - BlockContentComment *parseBlockContent(); - FullComment *parseFullComment(); -}; - -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h deleted file mode 100644 index 6a80383..0000000 --- a/include/clang/AST/CommentSema.h +++ /dev/null @@ -1,254 +0,0 @@ -//===--- CommentSema.h - Doxygen comment semantic analysis ------*- 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 semantic analysis class for Doxygen comments. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENTSEMA_H -#define LLVM_CLANG_AST_COMMENTSEMA_H - -#include "clang/AST/Comment.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Allocator.h" - -namespace clang { -class Decl; -class SourceMgr; -class Preprocessor; - -namespace comments { -class CommandTraits; - -class Sema { - Sema(const Sema &) = delete; - void operator=(const Sema &) = delete; - - /// Allocator for AST nodes. - llvm::BumpPtrAllocator &Allocator; - - /// Source manager for the comment being parsed. - const SourceManager &SourceMgr; - - DiagnosticsEngine &Diags; - - CommandTraits &Traits; - - const Preprocessor *PP; - - /// Information about the declaration this comment is attached to. - DeclInfo *ThisDeclInfo; - - /// Comment AST nodes that correspond to parameter names in - /// \c TemplateParameters. - /// - /// Contains a valid value if \c DeclInfo->IsFilled is true. - llvm::StringMap<TParamCommandComment *> TemplateParameterDocs; - - /// AST node for the \\brief command and its aliases. - const BlockCommandComment *BriefCommand; - - /// AST node for the \\headerfile command. - const BlockCommandComment *HeaderfileCommand; - - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(Loc, DiagID); - } - - /// A stack of HTML tags that are currently open (not matched with closing - /// tags). - SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags; - -public: - Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags, CommandTraits &Traits, - const Preprocessor *PP); - - void setDecl(const Decl *D); - - /// Returns a copy of array, owned by Sema's allocator. - template<typename T> - ArrayRef<T> copyArray(ArrayRef<T> Source) { - if (!Source.empty()) - return Source.copy(Allocator); - return None; - } - - ParagraphComment *actOnParagraphComment( - ArrayRef<InlineContentComment *> Content); - - BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker); - - void actOnBlockCommandArgs(BlockCommandComment *Command, - ArrayRef<BlockCommandComment::Argument> Args); - - void actOnBlockCommandFinish(BlockCommandComment *Command, - ParagraphComment *Paragraph); - - ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker); - - void actOnParamCommandDirectionArg(ParamCommandComment *Command, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg); - - void actOnParamCommandParamNameArg(ParamCommandComment *Command, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg); - - void actOnParamCommandFinish(ParamCommandComment *Command, - ParagraphComment *Paragraph); - - TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker); - - void actOnTParamCommandParamNameArg(TParamCommandComment *Command, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg); - - void actOnTParamCommandFinish(TParamCommandComment *Command, - ParagraphComment *Paragraph); - - InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, - SourceLocation CommandLocEnd, - unsigned CommandID); - - InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, - SourceLocation CommandLocEnd, - unsigned CommandID, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg); - - InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef CommandName); - - InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID); - - TextComment *actOnText(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef Text); - - VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc, - unsigned CommandID); - - VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc, - StringRef Text); - - void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, - SourceLocation CloseNameLocBegin, - StringRef CloseName, - ArrayRef<VerbatimBlockLineComment *> Lines); - - VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin, - unsigned CommandID, - SourceLocation TextBegin, - StringRef Text); - - HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin, - StringRef TagName); - - void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, - ArrayRef<HTMLStartTagComment::Attribute> Attrs, - SourceLocation GreaterLoc, - bool IsSelfClosing); - - HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef TagName); - - FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks); - - void checkBlockCommandEmptyParagraph(BlockCommandComment *Command); - - void checkReturnsCommand(const BlockCommandComment *Command); - - /// Emit diagnostics about duplicate block commands that should be - /// used only once per comment, e.g., \\brief and \\returns. - void checkBlockCommandDuplicate(const BlockCommandComment *Command); - - void checkDeprecatedCommand(const BlockCommandComment *Comment); - - void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment); - - void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment); - - void checkContainerDecl(const BlockCommandComment *Comment); - - /// Resolve parameter names to parameter indexes in function declaration. - /// Emit diagnostics about unknown parametrs. - void resolveParamCommandIndexes(const FullComment *FC); - - bool isFunctionDecl(); - bool isAnyFunctionDecl(); - - /// \returns \c true if declaration that this comment is attached to declares - /// a function pointer. - bool isFunctionPointerVarDecl(); - bool isFunctionOrMethodVariadic(); - bool isObjCMethodDecl(); - bool isObjCPropertyDecl(); - bool isTemplateOrSpecialization(); - bool isRecordLikeDecl(); - bool isClassOrStructDecl(); - bool isUnionDecl(); - bool isObjCInterfaceDecl(); - bool isObjCProtocolDecl(); - bool isClassTemplateDecl(); - bool isFunctionTemplateDecl(); - - ArrayRef<const ParmVarDecl *> getParamVars(); - - /// Extract all important semantic information from - /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members. - void inspectThisDecl(); - - /// Returns index of a function parameter with a given name. - unsigned resolveParmVarReference(StringRef Name, - ArrayRef<const ParmVarDecl *> ParamVars); - - /// Returns index of a function parameter with the name closest to a given - /// typo. - unsigned correctTypoInParmVarReference(StringRef Typo, - ArrayRef<const ParmVarDecl *> ParamVars); - - bool resolveTParamReference(StringRef Name, - const TemplateParameterList *TemplateParameters, - SmallVectorImpl<unsigned> *Position); - - StringRef correctTypoInTParamReference( - StringRef Typo, - const TemplateParameterList *TemplateParameters); - - InlineCommandComment::RenderKind - getInlineCommandRenderKind(StringRef Name) const; -}; - -} // end namespace comments -} // end namespace clang - -#endif - diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h deleted file mode 100644 index 21641bf..0000000 --- a/include/clang/AST/CommentVisitor.h +++ /dev/null @@ -1,70 +0,0 @@ -//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_COMMENTVISITOR_H -#define LLVM_CLANG_AST_COMMENTVISITOR_H - -#include "clang/AST/Comment.h" -#include "llvm/Support/ErrorHandling.h" - -namespace clang { -namespace comments { - -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; - -template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> -class CommentVisitorBase { -public: -#define PTR(CLASS) typename Ptr<CLASS>::type -#define DISPATCH(NAME, CLASS) \ - return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C)) - - RetTy visit(PTR(Comment) C) { - if (!C) - return RetTy(); - - switch (C->getCommentKind()) { - default: llvm_unreachable("Unknown comment kind!"); -#define ABSTRACT_COMMENT(COMMENT) -#define COMMENT(CLASS, PARENT) \ - case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS); -#include "clang/AST/CommentNodes.inc" -#undef ABSTRACT_COMMENT -#undef COMMENT - } - } - - // If the derived class does not implement a certain Visit* method, fall back - // on Visit* method for the superclass. -#define ABSTRACT_COMMENT(COMMENT) COMMENT -#define COMMENT(CLASS, PARENT) \ - RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); } -#include "clang/AST/CommentNodes.inc" -#undef ABSTRACT_COMMENT -#undef COMMENT - - RetTy visitComment(PTR(Comment) C) { return RetTy(); } - -#undef PTR -#undef DISPATCH -}; - -template<typename ImplClass, typename RetTy=void> -class CommentVisitor : - public CommentVisitorBase<make_ptr, ImplClass, RetTy> {}; - -template<typename ImplClass, typename RetTy=void> -class ConstCommentVisitor : - public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {}; - -} // end namespace comments -} // end namespace clang - -#endif diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h deleted file mode 100644 index 046ce70..0000000 --- a/include/clang/AST/Decl.h +++ /dev/null @@ -1,3801 +0,0 @@ -//===--- Decl.h - Classes for representing declarations ---------*- 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 Decl subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECL_H -#define LLVM_CLANG_AST_DECL_H - -#include "clang/AST/APValue.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/Redeclarable.h" -#include "clang/AST/Type.h" -#include "clang/Basic/Linkage.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/OperatorKinds.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TrailingObjects.h" - -namespace clang { -struct ASTTemplateArgumentListInfo; -class CXXTemporary; -class CompoundStmt; -class DependentFunctionTemplateSpecializationInfo; -class Expr; -class FunctionTemplateDecl; -class FunctionTemplateSpecializationInfo; -class LabelStmt; -class MemberSpecializationInfo; -class NestedNameSpecifier; -class ParmVarDecl; -class Stmt; -class StringLiteral; -class TemplateArgumentList; -class TemplateParameterList; -class TypeAliasTemplateDecl; -class TypeLoc; -class UnresolvedSetImpl; -class VarTemplateDecl; - -/// \brief A container of type source information. -/// -/// A client can read the relevant info using TypeLoc wrappers, e.g: -/// @code -/// TypeLoc TL = TypeSourceInfo->getTypeLoc(); -/// TL.getStartLoc().print(OS, SrcMgr); -/// @endcode -/// -class TypeSourceInfo { - QualType Ty; - // Contains a memory block after the class, used for type source information, - // allocated by ASTContext. - friend class ASTContext; - TypeSourceInfo(QualType ty) : Ty(ty) { } -public: - /// \brief Return the type wrapped by this type source info. - QualType getType() const { return Ty; } - - /// \brief Return the TypeLoc wrapper for the type source info. - TypeLoc getTypeLoc() const; // implemented in TypeLoc.h - - /// \brief Override the type stored in this TypeSourceInfo. Use with caution! - void overrideType(QualType T) { Ty = T; } -}; - -/// TranslationUnitDecl - The top declaration context. -class TranslationUnitDecl : public Decl, public DeclContext { - virtual void anchor(); - ASTContext &Ctx; - - /// The (most recently entered) anonymous namespace for this - /// translation unit, if one has been created. - NamespaceDecl *AnonymousNamespace; - - explicit TranslationUnitDecl(ASTContext &ctx); -public: - ASTContext &getASTContext() const { return Ctx; } - - NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } - void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } - - static TranslationUnitDecl *Create(ASTContext &C); - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == TranslationUnit; } - static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { - return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D)); - } - static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC)); - } -}; - -/// \brief Declaration context for names declared as extern "C" in C++. This -/// is neither the semantic nor lexical context for such declarations, but is -/// used to check for conflicts with other extern "C" declarations. Example: -/// -/// \code -/// namespace N { extern "C" void f(); } // #1 -/// void N::f() {} // #2 -/// namespace M { extern "C" void f(); } // #3 -/// \endcode -/// -/// The semantic context of #1 is namespace N and its lexical context is the -/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical -/// context is the TU. However, both declarations are also visible in the -/// extern "C" context. -/// -/// The declaration at #3 finds it is a redeclaration of \c N::f through -/// lookup in the extern "C" context. -class ExternCContextDecl : public Decl, public DeclContext { - virtual void anchor(); - - explicit ExternCContextDecl(TranslationUnitDecl *TU) - : Decl(ExternCContext, TU, SourceLocation()), - DeclContext(ExternCContext) {} -public: - static ExternCContextDecl *Create(const ASTContext &C, - TranslationUnitDecl *TU); - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ExternCContext; } - static DeclContext *castToDeclContext(const ExternCContextDecl *D) { - return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D)); - } - static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC)); - } -}; - -/// NamedDecl - This represents a decl with a name. Many decls have names such -/// as ObjCMethodDecl, but not \@class, etc. -class NamedDecl : public Decl { - virtual void anchor(); - /// Name - The name of this declaration, which is typically a normal - /// identifier but may also be a special kind of name (C++ - /// constructor, Objective-C selector, etc.) - DeclarationName Name; - -private: - NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY; - -protected: - NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) - : Decl(DK, DC, L), Name(N) { } - -public: - /// getIdentifier - Get the identifier that names this declaration, - /// if there is one. This will return NULL if this declaration has - /// no name (e.g., for an unnamed class) or if the name is a special - /// name (C++ constructor, Objective-C selector, etc.). - IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } - - /// getName - Get the name of identifier for this declaration as a StringRef. - /// This requires that the declaration have a name and that it be a simple - /// identifier. - StringRef getName() const { - assert(Name.isIdentifier() && "Name is not a simple identifier"); - return getIdentifier() ? getIdentifier()->getName() : ""; - } - - /// getNameAsString - Get a human-readable name for the declaration, even if - /// it is one of the special kinds of names (C++ constructor, Objective-C - /// selector, etc). Creating this name requires expensive string - /// manipulation, so it should be called only when performance doesn't matter. - /// For simple declarations, getNameAsCString() should suffice. - // - // FIXME: This function should be renamed to indicate that it is not just an - // alternate form of getName(), and clients should move as appropriate. - // - // FIXME: Deprecated, move clients to getName(). - std::string getNameAsString() const { return Name.getAsString(); } - - void printName(raw_ostream &os) const { os << Name; } - - /// getDeclName - Get the actual, stored name of the declaration, - /// which may be a special name. - DeclarationName getDeclName() const { return Name; } - - /// \brief Set the name of this declaration. - void setDeclName(DeclarationName N) { Name = N; } - - /// printQualifiedName - Returns human-readable qualified name for - /// declaration, like A::B::i, for i being member of namespace A::B. - /// If declaration is not member of context which can be named (record, - /// namespace), it will return same result as printName(). - /// Creating this name is expensive, so it should be called only when - /// performance doesn't matter. - void printQualifiedName(raw_ostream &OS) const; - void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; - - // FIXME: Remove string version. - std::string getQualifiedNameAsString() const; - - /// getNameForDiagnostic - Appends a human-readable name for this - /// declaration into the given stream. - /// - /// This is the method invoked by Sema when displaying a NamedDecl - /// in a diagnostic. It does not necessarily produce the same - /// result as printName(); for example, class template - /// specializations are printed with their template arguments. - virtual void getNameForDiagnostic(raw_ostream &OS, - const PrintingPolicy &Policy, - bool Qualified) const; - - /// \brief Determine whether this declaration, if - /// known to be well-formed within its context, will replace the - /// declaration OldD if introduced into scope. A declaration will - /// replace another declaration if, for example, it is a - /// redeclaration of the same variable or function, but not if it is - /// a declaration of a different kind (function vs. class) or an - /// overloaded function. - /// - /// \param IsKnownNewer \c true if this declaration is known to be newer - /// than \p OldD (for instance, if this declaration is newly-created). - bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const; - - /// \brief Determine whether this declaration has linkage. - bool hasLinkage() const; - - using Decl::isModulePrivate; - using Decl::setModulePrivate; - - /// \brief Determine whether this declaration is hidden from name lookup. - bool isHidden() const { return Hidden; } - - /// \brief Set whether this declaration is hidden from name lookup. - void setHidden(bool Hide) { - assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) && - "declaration with no owning module can't be hidden"); - Hidden = Hide; - } - - /// \brief Determine whether this declaration is a C++ class member. - bool isCXXClassMember() const { - const DeclContext *DC = getDeclContext(); - - // C++0x [class.mem]p1: - // The enumerators of an unscoped enumeration defined in - // the class are members of the class. - if (isa<EnumDecl>(DC)) - DC = DC->getRedeclContext(); - - return DC->isRecord(); - } - - /// \brief Determine whether the given declaration is an instance member of - /// a C++ class. - bool isCXXInstanceMember() const; - - /// \brief Determine what kind of linkage this entity has. - /// This is not the linkage as defined by the standard or the codegen notion - /// of linkage. It is just an implementation detail that is used to compute - /// those. - Linkage getLinkageInternal() const; - - /// \brief Get the linkage from a semantic point of view. Entities in - /// anonymous namespaces are external (in c++98). - Linkage getFormalLinkage() const { - return clang::getFormalLinkage(getLinkageInternal()); - } - - /// \brief True if this decl has external linkage. - bool hasExternalFormalLinkage() const { - return isExternalFormalLinkage(getLinkageInternal()); - } - - bool isExternallyVisible() const { - return clang::isExternallyVisible(getLinkageInternal()); - } - - /// \brief Determines the visibility of this entity. - Visibility getVisibility() const { - return getLinkageAndVisibility().getVisibility(); - } - - /// \brief Determines the linkage and visibility of this entity. - LinkageInfo getLinkageAndVisibility() const; - - /// Kinds of explicit visibility. - enum ExplicitVisibilityKind { - VisibilityForType, - VisibilityForValue - }; - - /// \brief If visibility was explicitly specified for this - /// declaration, return that visibility. - Optional<Visibility> - getExplicitVisibility(ExplicitVisibilityKind kind) const; - - /// \brief True if the computed linkage is valid. Used for consistency - /// checking. Should always return true. - bool isLinkageValid() const; - - /// \brief True if something has required us to compute the linkage - /// of this declaration. - /// - /// Language features which can retroactively change linkage (like a - /// typedef name for linkage purposes) may need to consider this, - /// but hopefully only in transitory ways during parsing. - bool hasLinkageBeenComputed() const { - return hasCachedLinkage(); - } - - /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for - /// the underlying named decl. - NamedDecl *getUnderlyingDecl() { - // Fast-path the common case. - if (this->getKind() != UsingShadow && - this->getKind() != ObjCCompatibleAlias && - this->getKind() != NamespaceAlias) - return this; - - return getUnderlyingDeclImpl(); - } - const NamedDecl *getUnderlyingDecl() const { - return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); - } - - NamedDecl *getMostRecentDecl() { - return cast<NamedDecl>(static_cast<Decl *>(this)->getMostRecentDecl()); - } - const NamedDecl *getMostRecentDecl() const { - return const_cast<NamedDecl*>(this)->getMostRecentDecl(); - } - - ObjCStringFormatFamily getObjCFStringFormattingFamily() const; - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { - ND.printName(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 { - void anchor() override; - LabelStmt *TheStmt; - StringRef MSAsmName; - bool MSAsmNameResolved; - /// LocStart - For normal labels, this is the same as the main declaration - /// label, i.e., the location of the identifier; for GNU local labels, - /// this is the location of the __label__ keyword. - SourceLocation LocStart; - - LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, - LabelStmt *S, SourceLocation StartL) - : NamedDecl(Label, DC, IdentL, II), - TheStmt(S), - MSAsmNameResolved(false), - LocStart(StartL) {} - -public: - static LabelDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation IdentL, IdentifierInfo *II); - static LabelDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation IdentL, IdentifierInfo *II, - SourceLocation GnuLabelL); - static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - LabelStmt *getStmt() const { return TheStmt; } - void setStmt(LabelStmt *T) { TheStmt = T; } - - bool isGnuLocal() const { return LocStart != getLocation(); } - void setLocStart(SourceLocation L) { LocStart = L; } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(LocStart, getLocation()); - } - - bool isMSAsmLabel() const { return MSAsmName.size() != 0; } - bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; } - void setMSAsmLabel(StringRef Name); - StringRef getMSAsmLabel() const { return MSAsmName; } - void setMSAsmLabelResolved() { MSAsmNameResolved = true; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Label; } -}; - -/// NamespaceDecl - Represent a C++ namespace. -class NamespaceDecl : public NamedDecl, public DeclContext, - public Redeclarable<NamespaceDecl> -{ - /// LocStart - The starting location of the source range, pointing - /// to either the namespace or the inline keyword. - SourceLocation LocStart; - /// RBraceLoc - The ending location of the source range. - SourceLocation RBraceLoc; - - /// \brief A pointer to either the anonymous namespace that lives just inside - /// this namespace or to the first namespace in the chain (the latter case - /// only when this is not the first in the chain), along with a - /// boolean value indicating whether this is an inline namespace. - llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline; - - NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, NamespaceDecl *PrevDecl); - - typedef Redeclarable<NamespaceDecl> redeclarable_base; - NamespaceDecl *getNextRedeclarationImpl() override; - NamespaceDecl *getPreviousDeclImpl() override; - NamespaceDecl *getMostRecentDeclImpl() override; - -public: - static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - bool Inline, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - NamespaceDecl *PrevDecl); - - static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - /// \brief Returns true if this is an anonymous namespace declaration. - /// - /// For example: - /// \code - /// namespace { - /// ... - /// }; - /// \endcode - /// q.v. C++ [namespace.unnamed] - bool isAnonymousNamespace() const { - return !getIdentifier(); - } - - /// \brief Returns true if this is an inline namespace declaration. - bool isInline() const { - return AnonOrFirstNamespaceAndInline.getInt(); - } - - /// \brief Set whether this is an inline namespace declaration. - void setInline(bool Inline) { - AnonOrFirstNamespaceAndInline.setInt(Inline); - } - - /// \brief Get the original (first) namespace declaration. - NamespaceDecl *getOriginalNamespace(); - - /// \brief Get the original (first) namespace declaration. - const NamespaceDecl *getOriginalNamespace() const; - - /// \brief Return true if this declaration is an original (first) declaration - /// of the namespace. This is false for non-original (subsequent) namespace - /// declarations and anonymous namespaces. - bool isOriginalNamespace() const; - - /// \brief Retrieve the anonymous namespace nested inside this namespace, - /// if any. - NamespaceDecl *getAnonymousNamespace() const { - return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer(); - } - - void setAnonymousNamespace(NamespaceDecl *D) { - getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D); - } - - /// Retrieves the canonical declaration of this namespace. - NamespaceDecl *getCanonicalDecl() override { - return getOriginalNamespace(); - } - const NamespaceDecl *getCanonicalDecl() const { - return getOriginalNamespace(); - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(LocStart, RBraceLoc); - } - - SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } - SourceLocation getRBraceLoc() const { return RBraceLoc; } - void setLocStart(SourceLocation L) { LocStart = L; } - void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Namespace; } - static DeclContext *castToDeclContext(const NamespaceDecl *D) { - return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D)); - } - static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// ValueDecl - Represent the declaration of a variable (in which case it is -/// an lvalue) a function (in which case it is a function designator) or -/// an enum constant. -class ValueDecl : public NamedDecl { - void anchor() override; - QualType DeclType; - -protected: - ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T) - : NamedDecl(DK, DC, L, N), DeclType(T) {} -public: - QualType getType() const { return DeclType; } - void setType(QualType newType) { DeclType = newType; } - - /// \brief Determine whether this symbol is weakly-imported, - /// or declared with the weak or weak-ref attr. - bool isWeak() const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } -}; - -/// QualifierInfo - A struct with extended info about a syntactic -/// name qualifier, to be used for the case of out-of-line declarations. -struct QualifierInfo { - NestedNameSpecifierLoc QualifierLoc; - - /// NumTemplParamLists - The number of "outer" template parameter lists. - /// The count includes all of the template parameter lists that were matched - /// against the template-ids occurring into the NNS and possibly (in the - /// case of an explicit specialization) a final "template <>". - unsigned NumTemplParamLists; - - /// TemplParamLists - A new-allocated array of size NumTemplParamLists, - /// containing pointers to the "outer" template parameter lists. - /// It includes all of the template parameter lists that were matched - /// against the template-ids occurring into the NNS and possibly (in the - /// case of an explicit specialization) a final "template <>". - TemplateParameterList** TemplParamLists; - - /// Default constructor. - QualifierInfo() - : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {} - - /// setTemplateParameterListsInfo - Sets info about "outer" template - /// parameter lists. - void setTemplateParameterListsInfo(ASTContext &Context, - ArrayRef<TemplateParameterList *> TPLists); - -private: - // Copy constructor and copy assignment are disabled. - QualifierInfo(const QualifierInfo&) = delete; - QualifierInfo& operator=(const QualifierInfo&) = delete; -}; - -/// \brief Represents a ValueDecl that came out of a declarator. -/// Contains type source information through TypeSourceInfo. -class DeclaratorDecl : public ValueDecl { - // A struct representing both a TInfo and a syntactic qualifier, - // to be used for the (uncommon) case of out-of-line declarations. - struct ExtInfo : public QualifierInfo { - TypeSourceInfo *TInfo; - }; - - llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; - - /// InnerLocStart - The start of the source range for this declaration, - /// ignoring outer template declarations. - SourceLocation InnerLocStart; - - bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } - ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } - const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); } - -protected: - DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, - SourceLocation StartL) - : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) { - } - -public: - TypeSourceInfo *getTypeSourceInfo() const { - return hasExtInfo() - ? getExtInfo()->TInfo - : DeclInfo.get<TypeSourceInfo*>(); - } - void setTypeSourceInfo(TypeSourceInfo *TI) { - if (hasExtInfo()) - getExtInfo()->TInfo = TI; - else - DeclInfo = TI; - } - - /// getInnerLocStart - Return SourceLocation representing start of source - /// range ignoring outer template declarations. - SourceLocation getInnerLocStart() const { return InnerLocStart; } - void setInnerLocStart(SourceLocation L) { InnerLocStart = L; } - - /// getOuterLocStart - Return SourceLocation representing start of source - /// range taking into account any outer template declarations. - SourceLocation getOuterLocStart() const; - - SourceRange getSourceRange() const override LLVM_READONLY; - SourceLocation getLocStart() const LLVM_READONLY { - return getOuterLocStart(); - } - - /// \brief Retrieve the nested-name-specifier that qualifies the name of this - /// declaration, if it was present in the source. - NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : nullptr; - } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was - /// present in the source. - NestedNameSpecifierLoc getQualifierLoc() const { - return hasExtInfo() ? getExtInfo()->QualifierLoc - : NestedNameSpecifierLoc(); - } - - void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); - - unsigned getNumTemplateParameterLists() const { - return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; - } - TemplateParameterList *getTemplateParameterList(unsigned index) const { - assert(index < getNumTemplateParameterLists()); - return getExtInfo()->TemplParamLists[index]; - } - void setTemplateParameterListsInfo(ASTContext &Context, - ArrayRef<TemplateParameterList *> TPLists); - - SourceLocation getTypeSpecStartLoc() const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - 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 -/// which it was evaluated (if any), and whether or not the statement -/// is an integral constant expression (if known). -struct EvaluatedStmt { - EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), - CheckingICE(false), IsICE(false) { } - - /// \brief Whether this statement was already evaluated. - bool WasEvaluated : 1; - - /// \brief Whether this statement is being evaluated. - bool IsEvaluating : 1; - - /// \brief Whether we already checked whether this statement was an - /// integral constant expression. - bool CheckedICE : 1; - - /// \brief Whether we are checking whether this statement is an - /// integral constant expression. - bool CheckingICE : 1; - - /// \brief Whether this statement is an integral constant expression, - /// or in C++11, whether the statement is a constant expression. Only - /// valid if CheckedICE is true. - bool IsICE : 1; - - Stmt *Value; - APValue Evaluated; -}; - -/// VarDecl - An instance of this class is created to represent a variable -/// declaration or definition. -class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { -public: - /// getStorageClassSpecifierString - Return the string used to - /// specify the storage class \p SC. - /// - /// It is illegal to call this function with SC == None. - static const char *getStorageClassSpecifierString(StorageClass SC); - - /// \brief Initialization styles. - enum InitializationStyle { - CInit, ///< C-style initialization with assignment - CallInit, ///< Call-style initialization (C++98) - ListInit ///< Direct list-initialization (C++11) - }; - - /// \brief Kinds of thread-local storage. - enum TLSKind { - TLS_None, ///< Not a TLS variable. - TLS_Static, ///< TLS with a known-constant initializer. - TLS_Dynamic ///< TLS with a dynamic initializer. - }; - -protected: - // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we - // have allocated the auxilliary struct of information there. - // - // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for - // this as *many* VarDecls are ParmVarDecls that don't have default - // arguments. We could save some space by moving this pointer union to be - // allocated in trailing space when necessary. - typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType; - - /// \brief The initializer for this variable or, for a ParmVarDecl, the - /// C++ default argument. - mutable InitType Init; - -private: - class VarDeclBitfields { - friend class VarDecl; - friend class ASTDeclReader; - - unsigned SClass : 3; - unsigned TSCSpec : 2; - unsigned InitStyle : 2; - }; - enum { NumVarDeclBits = 7 }; - - friend class ASTDeclReader; - friend class StmtIteratorBase; - friend class ASTNodeImporter; - -protected: - enum { NumParameterIndexBits = 8 }; - - enum DefaultArgKind { - DAK_None, - DAK_Unparsed, - DAK_Uninstantiated, - DAK_Normal - }; - - class ParmVarDeclBitfields { - friend class ParmVarDecl; - friend class ASTDeclReader; - - unsigned : NumVarDeclBits; - - /// Whether this parameter inherits a default argument from a - /// prior declaration. - unsigned HasInheritedDefaultArg : 1; - - /// Describes the kind of default argument for this parameter. By default - /// this is none. If this is normal, then the default argument is stored in - /// the \c VarDecl initalizer expression unless we were unble to parse - /// (even an invalid) expression for the default argument. - unsigned DefaultArgKind : 2; - - /// Whether this parameter undergoes K&R argument promotion. - unsigned IsKNRPromoted : 1; - - /// Whether this parameter is an ObjC method parameter or not. - unsigned IsObjCMethodParam : 1; - - /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. - /// Otherwise, the number of function parameter scopes enclosing - /// the function parameter scope in which this parameter was - /// declared. - unsigned ScopeDepthOrObjCQuals : 7; - - /// The number of parameters preceding this parameter in the - /// function parameter scope in which it was declared. - unsigned ParameterIndex : NumParameterIndexBits; - }; - - class NonParmVarDeclBitfields { - friend class VarDecl; - friend class ASTDeclReader; - - unsigned : NumVarDeclBits; - - /// \brief Whether this variable is the exception variable in a C++ catch - /// or an Objective-C @catch statement. - unsigned ExceptionVar : 1; - - /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization - /// (NRVO). - unsigned NRVOVariable : 1; - - /// \brief Whether this variable is the for-range-declaration in a C++0x - /// for-range statement. - unsigned CXXForRangeDecl : 1; - - /// \brief Whether this variable is an ARC pseudo-__strong - /// variable; see isARCPseudoStrong() for details. - unsigned ARCPseudoStrong : 1; - - /// \brief Whether this variable is (C++0x) constexpr. - unsigned IsConstexpr : 1; - - /// \brief Whether this variable is a (C++ Concepts TS) concept. - unsigned IsConcept : 1; - - /// \brief Whether this variable is the implicit variable for a lambda - /// init-capture. - unsigned IsInitCapture : 1; - - /// \brief Whether this local extern variable's previous declaration was - /// declared in the same block scope. This controls whether we should merge - /// the type of this declaration with its previous declaration. - unsigned PreviousDeclInSameBlockScope : 1; - }; - - union { - unsigned AllBits; - VarDeclBitfields VarDeclBits; - ParmVarDeclBitfields ParmVarDeclBits; - NonParmVarDeclBitfields NonParmVarDeclBits; - }; - - VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, StorageClass SC); - - typedef Redeclarable<VarDecl> redeclarable_base; - VarDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - VarDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - VarDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - static VarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S); - - static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// \brief Returns the storage class as written in the source. For the - /// computed linkage of symbol, see getLinkage. - StorageClass getStorageClass() const { - return (StorageClass) VarDeclBits.SClass; - } - void setStorageClass(StorageClass SC); - - void setTSCSpec(ThreadStorageClassSpecifier TSC) { - VarDeclBits.TSCSpec = TSC; - assert(VarDeclBits.TSCSpec == TSC && "truncation"); - } - ThreadStorageClassSpecifier getTSCSpec() const { - return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec); - } - TLSKind getTLSKind() const; - - /// hasLocalStorage - Returns true if a variable with function scope - /// is a non-static local variable. - bool hasLocalStorage() const { - if (getStorageClass() == SC_None) - // Second check is for C++11 [dcl.stc]p4. - return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; - - // Global Named Register (GNU extension) - if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm()) - return false; - - // Return true for: Auto, Register. - // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal. - - return getStorageClass() >= SC_Auto; - } - - /// isStaticLocal - Returns true if a variable with function scope is a - /// static local variable. - bool isStaticLocal() const { - return (getStorageClass() == SC_Static || - // C++11 [dcl.stc]p4 - (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local)) - && !isFileVarDecl(); - } - - /// \brief Returns true if a variable has extern or __private_extern__ - /// storage. - bool hasExternalStorage() const { - return getStorageClass() == SC_Extern || - getStorageClass() == SC_PrivateExtern; - } - - /// \brief Returns true for all variables that do not have local storage. - /// - /// This includes all global variables as well as static variables declared - /// within a function. - bool hasGlobalStorage() const { return !hasLocalStorage(); } - - /// \brief Get the storage duration of this variable, per C++ [basic.stc]. - StorageDuration getStorageDuration() const { - return hasLocalStorage() ? SD_Automatic : - getTSCSpec() ? SD_Thread : SD_Static; - } - - /// \brief Compute the language linkage. - LanguageLinkage getLanguageLinkage() const; - - /// \brief Determines whether this variable is a variable with - /// external, C linkage. - bool isExternC() const; - - /// \brief Determines whether this variable's context is, or is nested within, - /// a C++ extern "C" linkage spec. - bool isInExternCContext() const; - - /// \brief Determines whether this variable's context is, or is nested within, - /// a C++ extern "C++" linkage spec. - bool isInExternCXXContext() const; - - /// 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 isLocalVarDecl() const { - if (getKind() != Decl::Var) - return false; - if (const DeclContext *DC = getLexicalDeclContext()) - return DC->getRedeclContext()->isFunctionOrMethod(); - return false; - } - - /// \brief Similar to isLocalVarDecl but also includes parameters. - bool isLocalVarDeclOrParm() const { - return isLocalVarDecl() || getKind() == Decl::ParmVar; - } - - /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but - /// excludes variables declared in blocks. - bool isFunctionOrMethodVarDecl() const { - if (getKind() != Decl::Var) - return false; - const DeclContext *DC = getLexicalDeclContext()->getRedeclContext(); - return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block; - } - - /// \brief Determines whether this is a static data member. - /// - /// This will only be true in C++, and applies to, e.g., the - /// variable 'x' in: - /// \code - /// struct S { - /// static int x; - /// }; - /// \endcode - bool isStaticDataMember() const { - // If it wasn't static, it would be a FieldDecl. - return getKind() != Decl::ParmVar && getDeclContext()->isRecord(); - } - - VarDecl *getCanonicalDecl() override; - const VarDecl *getCanonicalDecl() const { - return const_cast<VarDecl*>(this)->getCanonicalDecl(); - } - - enum DefinitionKind { - DeclarationOnly, ///< This declaration is only a declaration. - TentativeDefinition, ///< This declaration is a tentative definition. - Definition ///< This declaration is definitely a definition. - }; - - /// \brief Check whether this declaration is a definition. If this could be - /// a tentative definition (in C), don't check whether there's an overriding - /// definition. - DefinitionKind isThisDeclarationADefinition(ASTContext &) const; - DefinitionKind isThisDeclarationADefinition() const { - return isThisDeclarationADefinition(getASTContext()); - } - - /// \brief Check whether this variable is defined in this - /// translation unit. - DefinitionKind hasDefinition(ASTContext &) const; - DefinitionKind hasDefinition() const { - return hasDefinition(getASTContext()); - } - - /// \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(); - const VarDecl *getActingDefinition() const { - return const_cast<VarDecl*>(this)->getActingDefinition(); - } - - /// \brief Get the real (not just tentative) definition for this declaration. - VarDecl *getDefinition(ASTContext &); - const VarDecl *getDefinition(ASTContext &C) const { - return const_cast<VarDecl*>(this)->getDefinition(C); - } - VarDecl *getDefinition() { - return getDefinition(getASTContext()); - } - const VarDecl *getDefinition() const { - return const_cast<VarDecl*>(this)->getDefinition(); - } - - /// \brief Determine whether this is or was instantiated from an out-of-line - /// definition of a static data member. - bool isOutOfLine() const override; - - /// \brief If this is a static data member, find its out-of-line definition. - VarDecl *getOutOfLineDefinition(); - - /// isFileVarDecl - Returns true for file scoped variable declaration. - bool isFileVarDecl() const { - Kind K = getKind(); - if (K == ParmVar || K == ImplicitParam) - return false; - - if (getLexicalDeclContext()->getRedeclContext()->isFileContext()) - return true; - - if (isStaticDataMember()) - return true; - - return false; - } - - /// getAnyInitializer - Get the initializer for this variable, no matter which - /// declaration it is attached to. - const Expr *getAnyInitializer() const { - const VarDecl *D; - return getAnyInitializer(D); - } - - /// getAnyInitializer - Get the initializer for this variable, no matter which - /// declaration it is attached to. Also get that declaration. - const Expr *getAnyInitializer(const VarDecl *&D) const; - - bool hasInit() const; - const Expr *getInit() const { - return const_cast<VarDecl *>(this)->getInit(); - } - Expr *getInit(); - - /// \brief Retrieve the address of the initializer expression. - Stmt **getInitAddress(); - - void setInit(Expr *I); - - /// \brief Determine whether this variable's value can be used in a - /// constant expression, according to the relevant language standard. - /// This only checks properties of the declaration, and does not check - /// whether the initializer is in fact a constant expression. - bool isUsableInConstantExpressions(ASTContext &C) const; - - EvaluatedStmt *ensureEvaluatedStmt() const; - - /// \brief Attempt to evaluate the value of the initializer attached to this - /// declaration, and produce notes explaining why it cannot be evaluated or is - /// not a constant expression. Returns a pointer to the value if evaluation - /// succeeded, 0 otherwise. - APValue *evaluateValue() const; - APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const; - - /// \brief Return the already-evaluated value of this variable's - /// initializer, or NULL if the value is not yet known. Returns pointer - /// to untyped APValue if the value could not be evaluated. - APValue *getEvaluatedValue() const; - - /// \brief Determines whether it is already known whether the - /// initializer is an integral constant expression or not. - bool isInitKnownICE() const; - - /// \brief Determines whether the initializer is an integral constant - /// expression, or in C++11, whether the initializer is a constant - /// expression. - /// - /// \pre isInitKnownICE() - bool isInitICE() const; - - /// \brief Determine whether the value of the initializer attached to this - /// declaration is an integral constant expression. - bool checkInitIsICE() const; - - void setInitStyle(InitializationStyle Style) { - VarDeclBits.InitStyle = Style; - } - - /// \brief The style of initialization for this declaration. - /// - /// C-style initialization is "int x = 1;". Call-style initialization is - /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be - /// the expression inside the parens or a "ClassType(a,b,c)" class constructor - /// expression for class types. List-style initialization is C++11 syntax, - /// e.g. "int x{1};". Clients can distinguish between different forms of - /// initialization by checking this value. In particular, "int x = {1};" is - /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the - /// Init expression in all three cases is an InitListExpr. - InitializationStyle getInitStyle() const { - return static_cast<InitializationStyle>(VarDeclBits.InitStyle); - } - - /// \brief Whether the initializer is a direct-initializer (list or call). - bool isDirectInit() const { - return getInitStyle() != CInit; - } - - /// \brief Determine whether this variable is the exception variable in a - /// C++ catch statememt or an Objective-C \@catch statement. - bool isExceptionVariable() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar; - } - void setExceptionVariable(bool EV) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.ExceptionVar = EV; - } - - /// \brief Determine whether this local variable can be used with the named - /// return value optimization (NRVO). - /// - /// The named return value optimization (NRVO) works by marking certain - /// non-volatile local variables of class type as NRVO objects. These - /// locals can be allocated within the return slot of their containing - /// function, in which case there is no need to copy the object to the - /// return slot when returning from the function. Within the function body, - /// each return that returns the NRVO object will have this variable as its - /// NRVO candidate. - bool isNRVOVariable() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.NRVOVariable; - } - void setNRVOVariable(bool NRVO) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.NRVOVariable = NRVO; - } - - /// \brief Determine whether this variable is the for-range-declaration in - /// a C++0x for-range statement. - bool isCXXForRangeDecl() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl; - } - void setCXXForRangeDecl(bool FRD) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.CXXForRangeDecl = FRD; - } - - /// \brief Determine whether this variable is an ARC pseudo-__strong - /// variable. A pseudo-__strong variable has a __strong-qualified - /// type but does not actually retain the object written into it. - /// Generally such variables are also 'const' for safety. - bool isARCPseudoStrong() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong; - } - void setARCPseudoStrong(bool ps) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.ARCPseudoStrong = ps; - } - - /// Whether this variable is (C++11) constexpr. - bool isConstexpr() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConstexpr; - } - void setConstexpr(bool IC) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.IsConstexpr = IC; - } - - /// Whether this variable is (C++ Concepts TS) concept. - bool isConcept() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept; - } - void setConcept(bool IC) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.IsConcept = IC; - } - - /// Whether this variable is the implicit variable for a lambda init-capture. - bool isInitCapture() const { - return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture; - } - void setInitCapture(bool IC) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.IsInitCapture = IC; - } - - /// Whether this local extern variable declaration's previous declaration - /// was declared in the same block scope. Only correct in C++. - bool isPreviousDeclInSameBlockScope() const { - return isa<ParmVarDecl>(this) - ? false - : NonParmVarDeclBits.PreviousDeclInSameBlockScope; - } - void setPreviousDeclInSameBlockScope(bool Same) { - assert(!isa<ParmVarDecl>(this)); - NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same; - } - - /// \brief If this variable is an instantiated static data member of a - /// class template specialization, returns the templated static data member - /// from which it was instantiated. - VarDecl *getInstantiatedFromStaticDataMember() const; - - /// \brief If this variable is an instantiation of a variable template or a - /// static data member of a class template, determine what kind of - /// template specialization or instantiation this is. - TemplateSpecializationKind getTemplateSpecializationKind() const; - - /// \brief If this variable is an instantiation of a variable template or a - /// static data member of a class template, determine its point of - /// instantiation. - SourceLocation getPointOfInstantiation() const; - - /// \brief If this variable is an instantiation of a static data member of a - /// class template specialization, retrieves the member specialization - /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const; - - /// \brief For a static data member that was instantiated from a static - /// data member of a class template, set the template specialiation kind. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK, - SourceLocation PointOfInstantiation = SourceLocation()); - - /// \brief Specify that this variable is an instantiation of the - /// static data member VD. - void setInstantiationOfStaticDataMember(VarDecl *VD, - TemplateSpecializationKind TSK); - - /// \brief Retrieves the variable template that is described by this - /// variable declaration. - /// - /// Every variable template is represented as a VarTemplateDecl and a - /// VarDecl. The former contains template properties (such as - /// the template parameter lists) while the latter contains the - /// actual description of the template's - /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the - /// VarDecl that from a VarTemplateDecl, while - /// getDescribedVarTemplate() retrieves the VarTemplateDecl from - /// a VarDecl. - VarTemplateDecl *getDescribedVarTemplate() const; - - void setDescribedVarTemplate(VarTemplateDecl *Template); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } -}; - -class ImplicitParamDecl : public VarDecl { - void anchor() override; -public: - static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T); - - static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, - IdentifierInfo *Id, QualType Type) - : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type, - /*tinfo*/ nullptr, SC_None) { - setImplicit(); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ImplicitParam; } -}; - -/// ParmVarDecl - Represents a parameter to a function. -class ParmVarDecl : public VarDecl { -public: - enum { MaxFunctionScopeDepth = 255 }; - enum { MaxFunctionScopeIndex = 255 }; - -protected: - ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) - : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) { - assert(ParmVarDeclBits.HasInheritedDefaultArg == false); - assert(ParmVarDeclBits.DefaultArgKind == DAK_None); - assert(ParmVarDeclBits.IsKNRPromoted == false); - assert(ParmVarDeclBits.IsObjCMethodParam == false); - setDefaultArg(DefArg); - } - -public: - static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg); - - static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - void setObjCMethodScopeInfo(unsigned parameterIndex) { - ParmVarDeclBits.IsObjCMethodParam = true; - setParameterIndex(parameterIndex); - } - - void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) { - assert(!ParmVarDeclBits.IsObjCMethodParam); - - ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; - assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth - && "truncation!"); - - setParameterIndex(parameterIndex); - } - - bool isObjCMethodParameter() const { - return ParmVarDeclBits.IsObjCMethodParam; - } - - unsigned getFunctionScopeDepth() const { - if (ParmVarDeclBits.IsObjCMethodParam) return 0; - return ParmVarDeclBits.ScopeDepthOrObjCQuals; - } - - /// Returns the index of this parameter in its prototype or method scope. - unsigned getFunctionScopeIndex() const { - return getParameterIndex(); - } - - ObjCDeclQualifier getObjCDeclQualifier() const { - if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None; - return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals); - } - void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { - assert(ParmVarDeclBits.IsObjCMethodParam); - ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal; - } - - /// True if the value passed to this parameter must undergo - /// K&R-style default argument promotion: - /// - /// C99 6.5.2.2. - /// If the expression that denotes the called function has a type - /// that does not include a prototype, the integer promotions are - /// performed on each argument, and arguments that have type float - /// are promoted to double. - bool isKNRPromoted() const { - return ParmVarDeclBits.IsKNRPromoted; - } - void setKNRPromoted(bool promoted) { - ParmVarDeclBits.IsKNRPromoted = promoted; - } - - Expr *getDefaultArg(); - const Expr *getDefaultArg() const { - return const_cast<ParmVarDecl *>(this)->getDefaultArg(); - } - - void setDefaultArg(Expr *defarg); - - /// \brief Retrieve the source range that covers the entire default - /// argument. - SourceRange getDefaultArgRange() const; - void setUninstantiatedDefaultArg(Expr *arg); - Expr *getUninstantiatedDefaultArg(); - const Expr *getUninstantiatedDefaultArg() const { - return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg(); - } - - /// hasDefaultArg - Determines whether this parameter has a default argument, - /// either parsed or not. - bool hasDefaultArg() const; - - /// hasUnparsedDefaultArg - Determines whether this parameter has a - /// default argument that has not yet been parsed. This will occur - /// during the processing of a C++ class whose member functions have - /// default arguments, e.g., - /// @code - /// class X { - /// public: - /// void f(int x = 17); // x has an unparsed default argument now - /// }; // x has a regular default argument now - /// @endcode - bool hasUnparsedDefaultArg() const { - return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed; - } - - bool hasUninstantiatedDefaultArg() const { - return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated; - } - - /// setUnparsedDefaultArg - Specify that this parameter has an - /// unparsed default argument. The argument will be replaced with a - /// real default argument via setDefaultArg when the class - /// definition enclosing the function declaration that owns this - /// default argument is completed. - void setUnparsedDefaultArg() { - ParmVarDeclBits.DefaultArgKind = DAK_Unparsed; - } - - bool hasInheritedDefaultArg() const { - return ParmVarDeclBits.HasInheritedDefaultArg; - } - - void setHasInheritedDefaultArg(bool I = true) { - ParmVarDeclBits.HasInheritedDefaultArg = I; - } - - QualType getOriginalType() const; - - /// \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 - /// the DeclContext appropriately. - void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ParmVar; } - -private: - enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; - - void setParameterIndex(unsigned parameterIndex) { - if (parameterIndex >= ParameterIndexSentinel) { - setParameterIndexLarge(parameterIndex); - return; - } - - ParmVarDeclBits.ParameterIndex = parameterIndex; - assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); - } - unsigned getParameterIndex() const { - unsigned d = ParmVarDeclBits.ParameterIndex; - return d == ParameterIndexSentinel ? getParameterIndexLarge() : d; - } - - void setParameterIndexLarge(unsigned parameterIndex); - unsigned getParameterIndexLarge() const; -}; - -/// FunctionDecl - An instance of this class is created to represent a -/// function declaration or definition. -/// -/// Since a given function can be declared several times in a program, -/// there may be several FunctionDecls that correspond to that -/// function. Only one of those FunctionDecls will be found when -/// traversing the list of declarations in the context of the -/// FunctionDecl (e.g., the translation unit); this FunctionDecl -/// contains all of the information known about the function. Other, -/// previous declarations of the function are available via the -/// getPreviousDecl() chain. -class FunctionDecl : public DeclaratorDecl, public DeclContext, - public Redeclarable<FunctionDecl> { -public: - /// \brief The kind of templated function a FunctionDecl can be. - enum TemplatedKind { - TK_NonTemplate, - TK_FunctionTemplate, - TK_MemberSpecialization, - TK_FunctionTemplateSpecialization, - TK_DependentFunctionTemplateSpecialization - }; - -private: - /// ParamInfo - new[]'d array of pointers to VarDecls for the formal - /// parameters of this function. This is null if a prototype or if there are - /// no formals. - ParmVarDecl **ParamInfo; - - /// DeclsInPrototypeScope - Array of pointers to NamedDecls for - /// decls defined in the function prototype that are not parameters. E.g. - /// 'enum Y' in 'void f(enum Y {AA} x) {}'. - ArrayRef<NamedDecl *> DeclsInPrototypeScope; - - LazyDeclStmtPtr Body; - - // FIXME: This can be packed into the bitfields in DeclContext. - // NOTE: VC++ packs bitfields poorly if the types differ. - unsigned SClass : 2; - unsigned IsInline : 1; - unsigned IsInlineSpecified : 1; - unsigned IsVirtualAsWritten : 1; - unsigned IsPure : 1; - unsigned HasInheritedPrototype : 1; - unsigned HasWrittenPrototype : 1; - unsigned IsDeleted : 1; - unsigned IsTrivial : 1; // sunk from CXXMethodDecl - unsigned IsDefaulted : 1; // sunk from CXXMethoDecl - unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl - unsigned HasImplicitReturnZero : 1; - unsigned IsLateTemplateParsed : 1; - unsigned IsConstexpr : 1; - - /// \brief Indicates if the function uses __try. - unsigned UsesSEHTry : 1; - - /// \brief Indicates if the function was a definition but its body was - /// skipped. - unsigned HasSkippedBody : 1; - - /// \brief End part of this FunctionDecl's source range. - /// - /// We could compute the full range in getSourceRange(). However, when we're - /// dealing with a function definition deserialized from a PCH/AST file, - /// we can only compute the full range once the function body has been - /// de-serialized, so it's far better to have the (sometimes-redundant) - /// EndRangeLoc. - SourceLocation EndRangeLoc; - - /// \brief The template or declaration that this declaration - /// describes or was instantiated from, respectively. - /// - /// For non-templates, this value will be NULL. For function - /// declarations that describe a function template, this will be a - /// pointer to a FunctionTemplateDecl. For member functions - /// of class template specializations, this will be a MemberSpecializationInfo - /// pointer containing information about the specialization. - /// For function template specializations, this will be a - /// FunctionTemplateSpecializationInfo, which contains information about - /// the template being specialized and the template arguments involved in - /// that specialization. - llvm::PointerUnion4<FunctionTemplateDecl *, - MemberSpecializationInfo *, - FunctionTemplateSpecializationInfo *, - DependentFunctionTemplateSpecializationInfo *> - TemplateOrSpecialization; - - /// DNLoc - Provides source/type location info for the - /// 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, ArrayRef<ParmVarDecl *> NewParamInfo); - -protected: - FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass S, bool isInlineSpecified, - bool isConstexprSpecified) - : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, - StartLoc), - DeclContext(DK), - redeclarable_base(C), - ParamInfo(nullptr), Body(), - SClass(S), - IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), - IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), - HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - IsDefaulted(false), IsExplicitlyDefaulted(false), - HasImplicitReturnZero(false), IsLateTemplateParsed(false), - IsConstexpr(isConstexprSpecified), UsesSEHTry(false), - HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()), - TemplateOrSpecialization(), - DNLoc(NameInfo.getInfo()) {} - - typedef Redeclarable<FunctionDecl> redeclarable_base; - FunctionDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - FunctionDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - FunctionDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation NLoc, - DeclarationName N, QualType T, - TypeSourceInfo *TInfo, - StorageClass SC, - bool isInlineSpecified = false, - bool hasWrittenPrototype = true, - bool isConstexprSpecified = false) { - DeclarationNameInfo NameInfo(N, NLoc); - return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, - SC, - isInlineSpecified, hasWrittenPrototype, - isConstexprSpecified); - } - - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, - bool isInlineSpecified, - bool hasWrittenPrototype, - bool isConstexprSpecified = false); - - static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); - } - - void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, - bool Qualified) const override; - - void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// \brief Returns true if the function has a body (definition). The - /// function body might be in any of the (re-)declarations of this - /// function. The variant that accepts a FunctionDecl pointer will - /// set that function declaration to the actual declaration - /// containing the body (if there is one). - bool hasBody(const FunctionDecl *&Definition) const; - - bool hasBody() const override { - const FunctionDecl* Definition; - return hasBody(Definition); - } - - /// hasTrivialBody - Returns whether the function has a trivial body that does - /// not require any specific codegen. - bool hasTrivialBody() const; - - /// isDefined - Returns true if the function is defined at all, including - /// a deleted definition. Except for the behavior when the function is - /// deleted, behaves like hasBody. - bool isDefined(const FunctionDecl *&Definition) const; - - virtual bool isDefined() const { - const FunctionDecl* Definition; - return isDefined(Definition); - } - - /// getBody - Retrieve the body (definition) of the function. The - /// function body might be in any of the (re-)declarations of this - /// function. The variant that accepts a FunctionDecl pointer will - /// set that function declaration to the actual declaration - /// containing the body (if there is one). - /// NOTE: For checking if there is a body, use hasBody() instead, to avoid - /// unnecessary AST de-serialization of the body. - Stmt *getBody(const FunctionDecl *&Definition) const; - - Stmt *getBody() const override { - const FunctionDecl* Definition; - return getBody(Definition); - } - - /// isThisDeclarationADefinition - Returns whether this specific - /// declaration of the function is also a definition. This does not - /// determine whether the function has been defined (e.g., in a - /// previous definition); for that information, use isDefined. Note - /// that this returns false for a defaulted function unless that function - /// has been implicitly defined (possibly as deleted). - bool isThisDeclarationADefinition() const { - return IsDeleted || Body || IsLateTemplateParsed; - } - - /// doesThisDeclarationHaveABody - Returns whether this specific - /// declaration of the function has a body - that is, if it is a non- - /// deleted definition. - bool doesThisDeclarationHaveABody() const { - return Body || IsLateTemplateParsed; - } - - void setBody(Stmt *B); - void setLazyBody(uint64_t Offset) { Body = Offset; } - - /// Whether this function is variadic. - bool isVariadic() const; - - /// Whether this function is marked as virtual explicitly. - bool isVirtualAsWritten() const { return IsVirtualAsWritten; } - void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } - - /// Whether this virtual function is pure, i.e. makes the containing class - /// abstract. - bool isPure() const { return IsPure; } - void setPure(bool P = true); - - /// Whether this templated function will be late parsed. - bool isLateTemplateParsed() const { return IsLateTemplateParsed; } - void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; } - - /// Whether this function is "trivial" in some specialized C++ senses. - /// Can only be true for default constructors, copy constructors, - /// copy assignment operators, and destructors. Not meaningful until - /// the class has been fully built by Sema. - bool isTrivial() const { return IsTrivial; } - void setTrivial(bool IT) { IsTrivial = IT; } - - /// Whether this function is defaulted per C++0x. Only valid for - /// special member functions. - bool isDefaulted() const { return IsDefaulted; } - void setDefaulted(bool D = true) { IsDefaulted = D; } - - /// Whether this function is explicitly defaulted per C++0x. Only valid - /// for special member functions. - bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; } - void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; } - - /// Whether falling off this function implicitly returns null/zero. - /// If a more specific implicit return value is required, front-ends - /// should synthesize the appropriate return statements. - bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } - void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } - - /// \brief Whether this function has a prototype, either because one - /// was explicitly written or because it was "inherited" by merging - /// a declaration without a prototype with a declaration that has a - /// prototype. - bool hasPrototype() const { - return HasWrittenPrototype || HasInheritedPrototype; - } - - bool hasWrittenPrototype() const { return HasWrittenPrototype; } - - /// \brief Whether this function inherited its prototype from a - /// previous declaration. - bool hasInheritedPrototype() const { return HasInheritedPrototype; } - void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } - - /// Whether this is a (C++11) constexpr function or constexpr constructor. - bool isConstexpr() const { return IsConstexpr; } - void setConstexpr(bool IC) { IsConstexpr = IC; } - - /// \brief Indicates the function uses __try. - bool usesSEHTry() const { return UsesSEHTry; } - void setUsesSEHTry(bool UST) { UsesSEHTry = UST; } - - /// \brief Whether this function has been deleted. - /// - /// A function that is "deleted" (via the C++0x "= delete" syntax) - /// acts like a normal function, except that it cannot actually be - /// called or have its address taken. Deleted functions are - /// typically used in C++ overload resolution to attract arguments - /// whose type or lvalue/rvalue-ness would permit the use of a - /// different overload that would behave incorrectly. For example, - /// one might use deleted functions to ban implicit conversion from - /// a floating-point number to an Integer type: - /// - /// @code - /// struct Integer { - /// Integer(long); // construct from a long - /// Integer(double) = delete; // no construction from float or double - /// Integer(long double) = delete; // no construction from long double - /// }; - /// @endcode - // If a function is deleted, its first declaration must be. - bool isDeleted() const { return getCanonicalDecl()->IsDeleted; } - bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; } - void setDeletedAsWritten(bool D = true) { IsDeleted = D; } - - /// \brief Determines whether this function is "main", which is the - /// entry point into an executable program. - bool isMain() const; - - /// \brief Determines whether this function is a MSVCRT user defined entry - /// point. - bool isMSVCRTEntryPoint() const; - - /// \brief Determines whether this operator new or delete is one - /// of the reserved global placement operators: - /// void *operator new(size_t, void *); - /// void *operator new[](size_t, void *); - /// void operator delete(void *, void *); - /// void operator delete[](void *, void *); - /// These functions have special behavior under [new.delete.placement]: - /// These functions are reserved, a C++ program may not define - /// functions that displace the versions in the Standard C++ library. - /// The provisions of [basic.stc.dynamic] do not apply to these - /// reserved placement forms of operator new and operator delete. - /// - /// This function must be an allocation or deallocation function. - bool isReservedGlobalPlacementOperator() const; - - /// \brief Determines whether this function is one of the replaceable - /// global allocation functions: - /// void *operator new(size_t); - /// void *operator new(size_t, const std::nothrow_t &) noexcept; - /// void *operator new[](size_t); - /// void *operator new[](size_t, const std::nothrow_t &) noexcept; - /// void operator delete(void *) noexcept; - /// void operator delete(void *, std::size_t) noexcept; [C++1y] - /// void operator delete(void *, const std::nothrow_t &) noexcept; - /// void operator delete[](void *) noexcept; - /// void operator delete[](void *, std::size_t) noexcept; [C++1y] - /// void operator delete[](void *, const std::nothrow_t &) noexcept; - /// These functions have special behavior under C++1y [expr.new]: - /// An implementation is allowed to omit a call to a replaceable global - /// allocation function. [...] - bool isReplaceableGlobalAllocationFunction() const; - - /// Compute the language linkage. - LanguageLinkage getLanguageLinkage() const; - - /// \brief Determines whether this function is a function with - /// external, C linkage. - bool isExternC() const; - - /// \brief Determines whether this function's context is, or is nested within, - /// a C++ extern "C" linkage spec. - bool isInExternCContext() const; - - /// \brief Determines whether this function's context is, or is nested within, - /// a C++ extern "C++" linkage spec. - bool isInExternCXXContext() const; - - /// \brief Determines whether this is a global function. - bool isGlobal() const; - - /// \brief Determines whether this function is known to be 'noreturn', through - /// an attribute on its declaration or its type. - bool isNoReturn() const; - - /// \brief True if the function was a definition but its body was skipped. - bool hasSkippedBody() const { return HasSkippedBody; } - void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } - - void setPreviousDeclaration(FunctionDecl * PrevDecl); - - FunctionDecl *getCanonicalDecl() override; - const FunctionDecl *getCanonicalDecl() const { - return const_cast<FunctionDecl*>(this)->getCanonicalDecl(); - } - - unsigned getBuiltinID() const; - - // Iterator access to formal parameters. - unsigned param_size() const { return getNumParams(); } - typedef ParmVarDecl **param_iterator; - typedef ParmVarDecl * const *param_const_iterator; - typedef llvm::iterator_range<param_iterator> param_range; - typedef llvm::iterator_range<param_const_iterator> param_const_range; - - param_iterator param_begin() { return param_iterator(ParamInfo); } - param_iterator param_end() { - return param_iterator(ParamInfo + param_size()); - } - param_range params() { return param_range(param_begin(), param_end()); } - - param_const_iterator param_begin() const { - return param_const_iterator(ParamInfo); - } - param_const_iterator param_end() const { - return param_const_iterator(ParamInfo + param_size()); - } - param_const_range params() const { - return param_const_range(param_begin(), param_end()); - } - - /// getNumParams - Return the number of parameters this function must have - /// based on its FunctionType. This is the length of the ParamInfo array - /// after it has been created. - unsigned getNumParams() const; - - const ParmVarDecl *getParamDecl(unsigned i) const { - assert(i < getNumParams() && "Illegal param #"); - return ParamInfo[i]; - } - ParmVarDecl *getParamDecl(unsigned i) { - assert(i < getNumParams() && "Illegal param #"); - return ParamInfo[i]; - } - void setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { - setParams(getASTContext(), NewParamInfo); - } - - // ArrayRef iterface to parameters. - // FIXME: Should one day replace iterator interface. - ArrayRef<ParmVarDecl*> parameters() const { - return llvm::makeArrayRef(ParamInfo, getNumParams()); - } - - ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const { - return DeclsInPrototypeScope; - } - void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls); - - /// getMinRequiredArguments - Returns the minimum number of arguments - /// needed to call this function. This may be fewer than the number of - /// function parameters, if some of the parameters have default - /// arguments (in C++). - unsigned getMinRequiredArguments() const; - - QualType getReturnType() const { - return getType()->getAs<FunctionType>()->getReturnType(); - } - - /// \brief Attempt to compute an informative source range covering the - /// function return type. This may omit qualifiers and other information with - /// limited representation in the AST. - SourceRange getReturnTypeSourceRange() const; - - /// \brief Determine the type of an expression that calls this function. - QualType getCallResultType() const { - return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); - } - - /// \brief Returns true if this function or its return type has the - /// warn_unused_result attribute. If the return type has the attribute and - /// this function is a method of the return type's class, then false will be - /// returned to avoid spurious warnings on member methods such as assignment - /// operators. - bool hasUnusedResultAttr() const; - - /// \brief Returns the storage class as written in the source. For the - /// computed linkage of symbol, see getLinkage. - StorageClass getStorageClass() const { return StorageClass(SClass); } - - /// \brief Determine whether the "inline" keyword was specified for this - /// function. - bool isInlineSpecified() const { return IsInlineSpecified; } - - /// Set whether the "inline" keyword was specified for this function. - 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 "constexpr" or is a member function of a class - /// that was defined in the class body. - bool isInlined() const { return IsInline; } - - bool isInlineDefinitionExternallyVisible() const; - - bool isMSExternInline() const; - - bool doesDeclarationForceExternallyVisibleDefinition() const; - - /// isOverloadedOperator - Whether this function declaration - /// represents an C++ overloaded operator, e.g., "operator+". - bool isOverloadedOperator() const { - return getOverloadedOperator() != OO_None; - } - - OverloadedOperatorKind getOverloadedOperator() const; - - const IdentifierInfo *getLiteralIdentifier() const; - - /// \brief If this function is an instantiation of a member function - /// of a class template specialization, retrieves the function from - /// which it was instantiated. - /// - /// This routine will return non-NULL for (non-templated) member - /// functions of class templates and for instantiations of function - /// templates. For example, given: - /// - /// \code - /// template<typename T> - /// struct X { - /// void f(T); - /// }; - /// \endcode - /// - /// The declaration for X<int>::f is a (non-templated) FunctionDecl - /// whose parent is the class template specialization X<int>. For - /// this declaration, getInstantiatedFromFunction() will return - /// the FunctionDecl X<T>::A. When a complete definition of - /// X<int>::A is required, it will be instantiated from the - /// declaration returned by getInstantiatedFromMemberFunction(). - FunctionDecl *getInstantiatedFromMemberFunction() const; - - /// \brief What kind of templated function this is. - TemplatedKind getTemplatedKind() const; - - /// \brief If this function is an instantiation of a member function of a - /// class template specialization, retrieves the member specialization - /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const; - - /// \brief Specify that this record is an instantiation of the - /// member function FD. - void setInstantiationOfMemberFunction(FunctionDecl *FD, - TemplateSpecializationKind TSK) { - setInstantiationOfMemberFunction(getASTContext(), FD, TSK); - } - - /// \brief Retrieves the function template that is described by this - /// function declaration. - /// - /// Every function template is represented as a FunctionTemplateDecl - /// and a FunctionDecl (or something derived from FunctionDecl). The - /// former contains template properties (such as the template - /// parameter lists) while the latter contains the actual - /// description of the template's - /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the - /// FunctionDecl that describes the function template, - /// getDescribedFunctionTemplate() retrieves the - /// FunctionTemplateDecl from a FunctionDecl. - FunctionTemplateDecl *getDescribedFunctionTemplate() const; - - void setDescribedFunctionTemplate(FunctionTemplateDecl *Template); - - /// \brief Determine whether this function is a function template - /// specialization. - bool isFunctionTemplateSpecialization() const { - return getPrimaryTemplate() != nullptr; - } - - /// \brief Retrieve the class scope template pattern that this function - /// template specialization is instantiated from. - FunctionDecl *getClassScopeSpecializationPattern() const; - - /// \brief If this function is actually a function template specialization, - /// retrieve information about this function template specialization. - /// Otherwise, returns NULL. - FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const; - - /// \brief Determines whether this function is a function template - /// specialization or a member of a class template specialization that can - /// be implicitly instantiated. - bool isImplicitlyInstantiable() const; - - /// \brief Determines if the given function was instantiated from a - /// function template. - bool isTemplateInstantiation() const; - - /// \brief Retrieve the function declaration from which this function could - /// be instantiated, if it is an instantiation (rather than a non-template - /// or a specialization, for example). - FunctionDecl *getTemplateInstantiationPattern() const; - - /// \brief Retrieve the primary template that this function template - /// specialization either specializes or was instantiated from. - /// - /// If this function declaration is not a function template specialization, - /// returns NULL. - FunctionTemplateDecl *getPrimaryTemplate() const; - - /// \brief Retrieve the template arguments used to produce this function - /// template specialization from the primary template. - /// - /// If this function declaration is not a function template specialization, - /// returns NULL. - const TemplateArgumentList *getTemplateSpecializationArgs() const; - - /// \brief Retrieve the template argument list as written in the sources, - /// if any. - /// - /// If this function declaration is not a function template specialization - /// or if it had no explicit template argument list, returns NULL. - /// Note that it an explicit template argument list may be written empty, - /// e.g., template<> void foo<>(char* s); - const ASTTemplateArgumentListInfo* - getTemplateSpecializationArgsAsWritten() const; - - /// \brief Specify that this function declaration is actually a function - /// template specialization. - /// - /// \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(FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, - const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr, - SourceLocation PointOfInstantiation = SourceLocation()) { - setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs, - InsertPos, TSK, TemplateArgsAsWritten, - PointOfInstantiation); - } - - /// \brief Specifies that this function declaration is actually a - /// dependent function template specialization. - void setDependentTemplateSpecialization(ASTContext &Context, - const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); - - DependentFunctionTemplateSpecializationInfo * - getDependentSpecializationInfo() const; - - /// \brief Determine what kind of template instantiation this function - /// represents. - TemplateSpecializationKind getTemplateSpecializationKind() const; - - /// \brief Determine what kind of template instantiation this function - /// represents. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK, - SourceLocation PointOfInstantiation = SourceLocation()); - - /// \brief Retrieve the (first) point of instantiation of a function template - /// specialization or a member of a class template specialization. - /// - /// \returns the first point of instantiation, if this function was - /// instantiated from a template; otherwise, returns an invalid source - /// location. - SourceLocation getPointOfInstantiation() const; - - /// \brief Determine whether this is or was instantiated from an out-of-line - /// definition of a member function. - bool isOutOfLine() const override; - - /// \brief Identify a memory copying or setting function. - /// If the given function is a memory copy or setting function, returns - /// the corresponding Builtin ID. If the function is not a memory function, - /// returns 0. - unsigned getMemoryFunctionKind() const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstFunction && K <= lastFunction; - } - static DeclContext *castToDeclContext(const FunctionDecl *D) { - return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D)); - } - static FunctionDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - - -/// FieldDecl - An instance of this class is created by Sema::ActOnField to -/// represent a member of a struct/union/class. -class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { - // FIXME: This can be packed into the bitfields in Decl. - bool Mutable : 1; - mutable unsigned CachedFieldIndex : 31; - - /// The kinds of value we can store in InitializerOrBitWidth. - /// - /// Note that this is compatible with InClassInitStyle except for - /// ISK_CapturedVLAType. - enum InitStorageKind { - /// If the pointer is null, there's nothing special. Otherwise, - /// this is a bitfield and the pointer is the Expr* storing the - /// bit-width. - ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit, - - /// The pointer is an (optional due to delayed parsing) Expr* - /// holding the copy-initializer. - ISK_InClassCopyInit = (unsigned) ICIS_CopyInit, - - /// The pointer is an (optional due to delayed parsing) Expr* - /// holding the list-initializer. - ISK_InClassListInit = (unsigned) ICIS_ListInit, - - /// The pointer is a VariableArrayType* that's been captured; - /// the enclosing context is a lambda or captured statement. - ISK_CapturedVLAType, - }; - - /// \brief Storage for either the bit-width, the in-class - /// initializer, or the captured variable length array bound. - /// - /// We can safely combine these because in-class initializers are - /// not permitted for bit-fields, and both are exclusive with VLA - /// captures. - /// - /// If the storage kind is ISK_InClassCopyInit or - /// ISK_InClassListInit, but the initializer is null, then this - /// field has an in-class initializer which has not yet been parsed - /// and attached. - llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage; -protected: - FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, - InClassInitStyle InitStyle) - : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), - Mutable(Mutable), CachedFieldIndex(0), - InitStorage(BW, (InitStorageKind) InitStyle) { - assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield"); - } - -public: - static FieldDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, Expr *BW, bool Mutable, - InClassInitStyle InitStyle); - - static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// 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; } - - /// \brief Determines whether this field is a bitfield. - bool isBitField() const { - return InitStorage.getInt() == ISK_BitWidthOrNothing && - InitStorage.getPointer() != nullptr; - } - - /// @brief Determines whether this is an unnamed bitfield. - bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); } - - /// isAnonymousStructOrUnion - Determines whether this field is a - /// representative for an anonymous struct or union. Such fields are - /// unnamed and are implicitly generated by the implementation to - /// store the data for the anonymous union or struct. - bool isAnonymousStructOrUnion() const; - - Expr *getBitWidth() const { - return isBitField() - ? static_cast<Expr *>(InitStorage.getPointer()) - : nullptr; - } - unsigned getBitWidthValue(const ASTContext &Ctx) const; - - /// setBitWidth - Set the bit-field width for this member. - // Note: used by some clients (i.e., do not remove it). - void setBitWidth(Expr *Width) { - assert(InitStorage.getInt() == ISK_BitWidthOrNothing && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing); - } - - /// removeBitWidth - Remove the bit-field width from this member. - // Note: used by some clients (i.e., do not remove it). - void removeBitWidth() { - assert(isBitField() && "no bitfield width to remove"); - InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); - } - - /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which - /// this field has. - InClassInitStyle getInClassInitStyle() const { - InitStorageKind storageKind = InitStorage.getInt(); - return (storageKind == ISK_CapturedVLAType - ? ICIS_NoInit : (InClassInitStyle) storageKind); - } - - /// hasInClassInitializer - Determine whether this member has a C++11 in-class - /// initializer. - bool hasInClassInitializer() const { - return getInClassInitStyle() != ICIS_NoInit; - } - - /// getInClassInitializer - Get the C++11 in-class initializer for this - /// member, or null if one has not been set. If a valid declaration has an - /// in-class initializer, but this returns null, then we have not parsed and - /// attached it yet. - Expr *getInClassInitializer() const { - return hasInClassInitializer() - ? static_cast<Expr *>(InitStorage.getPointer()) - : nullptr; - } - - /// setInClassInitializer - Set the C++11 in-class initializer for this - /// member. - void setInClassInitializer(Expr *Init) { - assert(hasInClassInitializer() && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointer(Init); - } - - /// removeInClassInitializer - Remove the C++11 in-class initializer from this - /// member. - void removeInClassInitializer() { - assert(hasInClassInitializer() && "no initializer to remove"); - InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); - } - - /// \brief Determine whether this member captures the variable length array - /// type. - bool hasCapturedVLAType() const { - return InitStorage.getInt() == ISK_CapturedVLAType; - } - - /// \brief Get the captured variable length array type. - const VariableArrayType *getCapturedVLAType() const { - return hasCapturedVLAType() ? static_cast<const VariableArrayType *>( - InitStorage.getPointer()) - : nullptr; - } - /// \brief Set the captured variable length array type for this field. - void setCapturedVLAType(const VariableArrayType *VLAType); - - /// getParent - Returns the parent of this field declaration, which - /// is the struct in which this method is defined. - const RecordDecl *getParent() const { - return cast<RecordDecl>(getDeclContext()); - } - - RecordDecl *getParent() { - return cast<RecordDecl>(getDeclContext()); - } - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Retrieves the canonical declaration of this field. - FieldDecl *getCanonicalDecl() override { return getFirstDecl(); } - const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// EnumConstantDecl - An instance of this object exists for each enum constant -/// that is defined. For example, in "enum X {a,b}", each of a/b are -/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a -/// TagType for the X EnumDecl. -class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> { - Stmt *Init; // an integer constant expression - llvm::APSInt Val; // The value. -protected: - EnumConstantDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, Expr *E, - const llvm::APSInt &V) - : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} - -public: - - static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, Expr *E, - const llvm::APSInt &V); - static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - const Expr *getInitExpr() const { return (const Expr*) Init; } - Expr *getInitExpr() { return (Expr*) Init; } - const llvm::APSInt &getInitVal() const { return Val; } - - void setInitExpr(Expr *E) { Init = (Stmt*) E; } - void setInitVal(const llvm::APSInt &V) { Val = V; } - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Retrieves the canonical declaration of this enumerator. - EnumConstantDecl *getCanonicalDecl() override { return getFirstDecl(); } - const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == EnumConstant; } - - 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, - public Mergeable<IndirectFieldDecl> { - void anchor() override; - 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); - - static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - typedef NamedDecl * const *chain_iterator; - typedef llvm::iterator_range<chain_iterator> chain_range; - - chain_range chain() const { return chain_range(chain_begin(), chain_end()); } - chain_iterator chain_begin() const { return chain_iterator(Chaining); } - chain_iterator chain_end() const { - return chain_iterator(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()); - } - - IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); } - const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == IndirectField; } - friend class ASTDeclReader; -}; - -/// TypeDecl - Represents a declaration of a type. -/// -class TypeDecl : public NamedDecl { - void anchor() override; - /// TypeForDecl - This indicates the Type object that represents - /// this TypeDecl. It is a cache maintained by - /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and - /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. - mutable const Type *TypeForDecl; - /// LocStart - The start of the source range for this declaration. - SourceLocation LocStart; - friend class ASTContext; - -protected: - TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation StartL = SourceLocation()) - : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {} - -public: - // Low-level accessor. If you just want the type defined by this node, - // check out ASTContext::getTypeDeclType or one of - // ASTContext::getTypedefType, ASTContext::getRecordType, etc. if you - // already know the specific kind of node this is. - const Type *getTypeForDecl() const { return TypeForDecl; } - void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } - - SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } - void setLocStart(SourceLocation L) { LocStart = L; } - SourceRange getSourceRange() const override LLVM_READONLY { - if (LocStart.isValid()) - return SourceRange(LocStart, getLocation()); - else - return SourceRange(getLocation()); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstType && K <= lastType; } -}; - - -/// Base class for declarations which introduce a typedef-name. -class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { - void anchor() override; - typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo; - llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo; - -protected: - TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C), - MaybeModedTInfo(TInfo) {} - - typedef Redeclarable<TypedefNameDecl> redeclarable_base; - TypedefNameDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - TypedefNameDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - TypedefNameDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); } - - TypeSourceInfo *getTypeSourceInfo() const { - return isModed() - ? MaybeModedTInfo.get<ModedTInfo*>()->first - : MaybeModedTInfo.get<TypeSourceInfo*>(); - } - QualType getUnderlyingType() const { - return isModed() - ? MaybeModedTInfo.get<ModedTInfo*>()->second - : MaybeModedTInfo.get<TypeSourceInfo*>()->getType(); - } - void setTypeSourceInfo(TypeSourceInfo *newType) { - MaybeModedTInfo = newType; - } - void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) { - MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy); - } - - /// Retrieves the canonical declaration of this typedef-name. - TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); } - const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); } - - /// Retrieves the tag declaration for which this is the typedef name for - /// linkage purposes, if any. - /// - /// \param AnyRedecl Look for the tag declaration in any redeclaration of - /// this typedef declaration. - TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstTypedefName && K <= lastTypedefName; - } -}; - -/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' -/// type specifier. -class TypedefDecl : public TypedefNameDecl { - TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {} - -public: - static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo); - static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Typedef; } -}; - -/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x -/// alias-declaration. -class TypeAliasDecl : public TypedefNameDecl { - /// The template for which this is the pattern, if any. - TypeAliasTemplateDecl *Template; - - TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo), - Template(nullptr) {} - -public: - static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo); - static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; } - void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == TypeAlias; } -}; - -/// TagDecl - Represents the declaration of a struct/union/class/enum. -class TagDecl - : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { -public: - // This is really ugly. - typedef TagTypeKind TagKind; - -private: - // FIXME: This can be packed into the bitfields in Decl. - /// TagDeclKind - The TagKind enum. - unsigned TagDeclKind : 3; - - /// IsCompleteDefinition - True if this is a definition ("struct foo - /// {};"), false if it is a declaration ("struct foo;"). It is not - /// a definition until the definition has been fully processed. - bool IsCompleteDefinition : 1; - -protected: - /// IsBeingDefined - True if this is currently being defined. - bool IsBeingDefined : 1; - -private: - /// IsEmbeddedInDeclarator - True if this tag declaration is - /// "embedded" (i.e., defined or declared for the very first time) - /// in the syntax of a declarator. - bool IsEmbeddedInDeclarator : 1; - - /// \brief True if this tag is free standing, e.g. "struct foo;". - bool IsFreeStanding : 1; - -protected: - // These are used by (and only defined for) EnumDecl. - unsigned NumPositiveBits : 8; - unsigned NumNegativeBits : 8; - - /// IsScoped - True if this tag declaration is a scoped enumeration. Only - /// possible in C++11 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++11, Microsoft extensions, or Objective C mode. - bool IsFixed : 1; - - /// \brief Indicates whether it is possible for declarations of this kind - /// to have an out-of-date definition. - /// - /// This option is only enabled when modules are enabled. - bool MayHaveOutOfDateDef : 1; - - /// Has the full definition of this type been required by a use somewhere in - /// the TU. - bool IsCompleteDefinitionRequired : 1; -private: - SourceLocation RBraceLoc; - - // A struct representing syntactic qualifier info, - // to be used for the (uncommon) case of out-of-line declarations. - typedef QualifierInfo ExtInfo; - - /// \brief If the (out-of-line) tag declaration name - /// is qualified, it points to the qualifier info (nns and range); - /// otherwise, if the tag declaration is anonymous and it is part of - /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); - /// otherwise, if the tag declaration is anonymous and it is used as a - /// declaration specifier for variables, it points to the first VarDecl (used - /// for mangling); - /// otherwise, it is a null (TypedefNameDecl) pointer. - llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier; - - bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); } - ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } - const ExtInfo *getExtInfo() const { - return TypedefNameDeclOrQualifier.get<ExtInfo *>(); - } - -protected: - TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, - SourceLocation StartL) - : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C), - TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false), - IsEmbeddedInDeclarator(false), IsFreeStanding(false), - IsCompleteDefinitionRequired(false), - TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { - assert((DK != Enum || TK == TTK_Enum) && - "EnumDecl not matched with TTK_Enum"); - setPreviousDecl(PrevDecl); - } - - typedef Redeclarable<TagDecl> redeclarable_base; - TagDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - TagDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - TagDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - - /// @brief Completes the definition of this tag declaration. - /// - /// This is a helper function for derived classes. - void completeDefinition(); - -public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - SourceLocation getRBraceLoc() const { return RBraceLoc; } - void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - - /// getInnerLocStart - Return SourceLocation representing start of source - /// range ignoring outer template declarations. - SourceLocation getInnerLocStart() const { return getLocStart(); } - - /// getOuterLocStart - Return SourceLocation representing start of source - /// range taking into account any outer template declarations. - SourceLocation getOuterLocStart() const; - SourceRange getSourceRange() const override LLVM_READONLY; - - TagDecl *getCanonicalDecl() override; - const TagDecl *getCanonicalDecl() const { - return const_cast<TagDecl*>(this)->getCanonicalDecl(); - } - - /// isThisDeclarationADefinition() - Return true if this declaration - /// is a completion definition of the type. Provided for consistency. - bool isThisDeclarationADefinition() const { - return isCompleteDefinition(); - } - - /// isCompleteDefinition - Return true if this decl has its body - /// fully specified. - bool isCompleteDefinition() const { - return IsCompleteDefinition; - } - - /// \brief Return true if this complete decl is - /// required to be complete for some existing use. - bool isCompleteDefinitionRequired() const { - return IsCompleteDefinitionRequired; - } - - /// isBeingDefined - Return true if this decl is currently being defined. - bool isBeingDefined() const { - return IsBeingDefined; - } - - bool isEmbeddedInDeclarator() const { - return IsEmbeddedInDeclarator; - } - void setEmbeddedInDeclarator(bool isInDeclarator) { - IsEmbeddedInDeclarator = isInDeclarator; - } - - bool isFreeStanding() const { return IsFreeStanding; } - void setFreeStanding(bool isFreeStanding = true) { - IsFreeStanding = isFreeStanding; - } - - /// \brief Whether this declaration declares a type that is - /// dependent, i.e., a type that somehow depends on template - /// parameters. - bool isDependentType() const { return isDependentContext(); } - - /// @brief Starts the definition of this tag declaration. - /// - /// This method should be invoked at the beginning of the definition - /// of this tag declaration. It will set the tag type into a state - /// where it is in the process of being defined. - void startDefinition(); - - /// getDefinition - Returns the TagDecl that actually defines this - /// struct/union/class/enum. When determining whether or not a - /// struct/union/class/enum has a definition, one should use this - /// method as opposed to 'isDefinition'. 'isDefinition' indicates - /// whether or not a specific TagDecl is defining declaration, not - /// whether or not the struct/union/class/enum type is defined. - /// This method returns NULL if there is no TagDecl that defines - /// the struct/union/class/enum. - TagDecl *getDefinition() const; - - void setCompleteDefinition(bool V) { IsCompleteDefinition = V; } - - void setCompleteDefinitionRequired(bool V = true) { - IsCompleteDefinitionRequired = V; - } - - StringRef getKindName() const { - return TypeWithKeyword::getTagTypeKindName(getTagKind()); - } - - TagKind getTagKind() const { - return TagKind(TagDeclKind); - } - - void setTagKind(TagKind TK) { TagDeclKind = TK; } - - bool isStruct() const { return getTagKind() == TTK_Struct; } - bool isInterface() const { return getTagKind() == TTK_Interface; } - bool isClass() const { return getTagKind() == TTK_Class; } - bool isUnion() const { return getTagKind() == TTK_Union; } - bool isEnum() const { return getTagKind() == TTK_Enum; } - - /// Is this tag type named, either directly or via being defined in - /// a typedef of this type? - /// - /// C++11 [basic.link]p8: - /// A type is said to have linkage if and only if: - /// - it is a class or enumeration type that is named (or has a - /// name for linkage purposes) and the name has linkage; ... - /// C++11 [dcl.typedef]p9: - /// If the typedef declaration defines an unnamed class (or enum), - /// the first typedef-name declared by the declaration to be that - /// class type (or enum type) is used to denote the class type (or - /// enum type) for linkage purposes only. - /// - /// C does not have an analogous rule, but the same concept is - /// nonetheless useful in some places. - bool hasNameForLinkage() const { - return (getDeclName() || getTypedefNameForAnonDecl()); - } - - TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? nullptr - : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>(); - } - - void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); - - /// \brief Retrieve the nested-name-specifier that qualifies the name of this - /// declaration, if it was present in the source. - NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : nullptr; - } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was - /// present in the source. - NestedNameSpecifierLoc getQualifierLoc() const { - return hasExtInfo() ? getExtInfo()->QualifierLoc - : NestedNameSpecifierLoc(); - } - - void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); - - unsigned getNumTemplateParameterLists() const { - return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; - } - TemplateParameterList *getTemplateParameterList(unsigned i) const { - assert(i < getNumTemplateParameterLists()); - return getExtInfo()->TemplParamLists[i]; - } - void setTemplateParameterListsInfo(ASTContext &Context, - ArrayRef<TemplateParameterList *> TPLists); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K >= firstTag && K <= lastTag; } - - static DeclContext *castToDeclContext(const TagDecl *D) { - return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); - } - static TagDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared -/// with a fixed underlying type, and in C we allow them to be forward-declared -/// with no underlying type as an extension. -class EnumDecl : public TagDecl { - void anchor() override; - /// 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. - /// - /// 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 - /// directly, but gcc-style large enumerators (and all enumerators - /// in C++) are of the enum type instead. - QualType PromotionType; - - /// \brief If this enumeration is an instantiation of a member enumeration - /// of a class template specialization, this is the member specialization - /// information. - MemberSpecializationInfo *SpecializationInfo; - - EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, - bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc), - SpecializationInfo(nullptr) { - assert(Scoped || !ScopedUsingClassTag); - IntegerType = (const Type *)nullptr; - NumNegativeBits = 0; - NumPositiveBits = 0; - IsScoped = Scoped; - IsScopedUsingClassTag = ScopedUsingClassTag; - IsFixed = Fixed; - } - - void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, - TemplateSpecializationKind TSK); -public: - EnumDecl *getCanonicalDecl() override { - return cast<EnumDecl>(TagDecl::getCanonicalDecl()); - } - const EnumDecl *getCanonicalDecl() const { - return const_cast<EnumDecl*>(this)->getCanonicalDecl(); - } - - EnumDecl *getPreviousDecl() { - return cast_or_null<EnumDecl>( - static_cast<TagDecl *>(this)->getPreviousDecl()); - } - const EnumDecl *getPreviousDecl() const { - return const_cast<EnumDecl*>(this)->getPreviousDecl(); - } - - EnumDecl *getMostRecentDecl() { - return cast<EnumDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl()); - } - const EnumDecl *getMostRecentDecl() const { - return const_cast<EnumDecl*>(this)->getMostRecentDecl(); - } - - EnumDecl *getDefinition() const { - return cast_or_null<EnumDecl>(TagDecl::getDefinition()); - } - - static EnumDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, EnumDecl *PrevDecl, - bool IsScoped, bool IsScopedUsingClassTag, - bool IsFixed); - static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// completeDefinition - When created, the EnumDecl corresponds to a - /// forward-declared enum. This method is used to mark the - /// declaration as being defined; it's enumerators have already been - /// added (via DeclContext::addDecl). NewType is the new underlying - /// type of the enumeration type. - void completeDefinition(QualType NewType, - QualType PromotionType, - unsigned NumPositiveBits, - unsigned NumNegativeBits); - - // enumerator_iterator - Iterates through the enumerators of this - // enumeration. - typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; - typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>> - enumerator_range; - - enumerator_range enumerators() const { - return enumerator_range(enumerator_begin(), enumerator_end()); - } - - enumerator_iterator enumerator_begin() const { - const EnumDecl *E = getDefinition(); - if (!E) - E = this; - return enumerator_iterator(E->decls_begin()); - } - - enumerator_iterator enumerator_end() const { - const EnumDecl *E = getDefinition(); - if (!E) - E = this; - return enumerator_iterator(E->decls_end()); - } - - /// getPromotionType - Return the integer type that enumerators - /// should promote to. - QualType getPromotionType() const { return PromotionType; } - - /// \brief Set the promotion type. - void setPromotionType(QualType T) { PromotionType = T; } - - /// getIntegerType - Return the integer type this enum decl corresponds to. - /// This returns a null QualType for an enum forward definition with no fixed - /// underlying type. - 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().getUnqualifiedType(); - } - - /// \brief Set the underlying integer type. - 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 Retrieve the source range that covers the underlying type if - /// specified. - SourceRange getIntegerTypeRange() const LLVM_READONLY; - - /// \brief Returns the width in bits required to store all the - /// non-negative enumerators of this enum. - unsigned getNumPositiveBits() const { - return NumPositiveBits; - } - void setNumPositiveBits(unsigned Num) { - NumPositiveBits = Num; - assert(NumPositiveBits == Num && "can't store this bitcount"); - } - - /// \brief Returns the width in bits required to store all the - /// negative enumerators of this enum. These widths include - /// the rightmost leading 1; that is: - /// - /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS - /// ------------------------ ------- ----------------- - /// -1 1111111 1 - /// -10 1110110 5 - /// -101 1001011 8 - unsigned getNumNegativeBits() const { - return NumNegativeBits; - } - void setNumNegativeBits(unsigned Num) { - NumNegativeBits = Num; - } - - /// \brief Returns true if this is a C++11 scoped enumeration. - bool isScoped() const { - return IsScoped; - } - - /// \brief Returns true if this is a C++11 scoped enumeration. - bool isScopedUsingClassTag() const { - return IsScopedUsingClassTag; - } - - /// \brief Returns true if this is an Objective-C, C++11, or - /// Microsoft-style enumeration with a fixed underlying type. - bool isFixed() const { - return IsFixed; - } - - /// \brief Returns true if this can be considered a complete type. - bool isComplete() const { - return isCompleteDefinition() || 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. - EnumDecl *getInstantiatedFromMemberEnum() const; - - /// \brief If this enumeration is a member of a specialization of a - /// templated class, determine what kind of template specialization - /// or instantiation this is. - TemplateSpecializationKind getTemplateSpecializationKind() const; - - /// \brief For an enumeration member that was instantiated from a member - /// enumeration of a templated class, set the template specialiation kind. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK, - SourceLocation PointOfInstantiation = SourceLocation()); - - /// \brief If this enumeration is an instantiation of a member enumeration of - /// a class template specialization, retrieves the member specialization - /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const { - return SpecializationInfo; - } - - /// \brief Specify that this enumeration is an instantiation of the - /// member enumeration ED. - void setInstantiationOfMemberEnum(EnumDecl *ED, - TemplateSpecializationKind TSK) { - setInstantiationOfMemberEnum(getASTContext(), ED, TSK); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Enum; } - - friend class ASTDeclReader; -}; - - -/// RecordDecl - Represents a struct/union/class. For example: -/// struct X; // Forward declaration, no "body". -/// union Y { int A, B; }; // Has body with members A and B (FieldDecls). -/// This decl will be marked invalid if *any* members are invalid. -/// -class RecordDecl : public TagDecl { - // FIXME: This can be packed into the bitfields in Decl. - /// HasFlexibleArrayMember - This is true if this struct ends with a flexible - /// array member (e.g. int X[]) or if this union contains a struct that does. - /// If so, this cannot be contained in arrays or other structs as a member. - bool HasFlexibleArrayMember : 1; - - /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct - /// or union. - bool AnonymousStructOrUnion : 1; - - /// HasObjectMember - This is true if this struct has at least one member - /// containing an Objective-C object pointer type. - bool HasObjectMember : 1; - - /// HasVolatileMember - This is true if struct has at least one member of - /// 'volatile' type. - bool HasVolatileMember : 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, const ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, RecordDecl *PrevDecl); - -public: - static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr); - static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - - RecordDecl *getPreviousDecl() { - return cast_or_null<RecordDecl>( - static_cast<TagDecl *>(this)->getPreviousDecl()); - } - const RecordDecl *getPreviousDecl() const { - return const_cast<RecordDecl*>(this)->getPreviousDecl(); - } - - RecordDecl *getMostRecentDecl() { - return cast<RecordDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl()); - } - const RecordDecl *getMostRecentDecl() const { - return const_cast<RecordDecl*>(this)->getMostRecentDecl(); - } - - bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } - void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } - - /// isAnonymousStructOrUnion - Whether this is an anonymous struct - /// or union. To be an anonymous struct or union, it must have been - /// declared without a name and there must be no objects of this - /// type declared, e.g., - /// @code - /// union { int i; float f; }; - /// @endcode - /// is an anonymous union but neither of the following are: - /// @code - /// union X { int i; float f; }; - /// union { int i; float f; } obj; - /// @endcode - bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; } - void setAnonymousStructOrUnion(bool Anon) { - AnonymousStructOrUnion = Anon; - } - - bool hasObjectMember() const { return HasObjectMember; } - void setHasObjectMember (bool val) { HasObjectMember = val; } - - bool hasVolatileMember() const { return HasVolatileMember; } - void setHasVolatileMember (bool val) { HasVolatileMember = val; } - - bool hasLoadedFieldsFromExternalStorage() const { - return LoadedFieldsFromExternalStorage; - } - void setHasLoadedFieldsFromExternalStorage(bool val) { - LoadedFieldsFromExternalStorage = val; - } - - /// \brief Determines whether this declaration represents the - /// injected class name. - /// - /// The injected class name in C++ is the name of the class that - /// appears inside the class itself. For example: - /// - /// \code - /// struct C { - /// // C is implicitly declared here as a synonym for the class name. - /// }; - /// - /// C::C c; // same as "C c;" - /// \endcode - bool isInjectedClassName() const; - - /// \brief Determine whether this record is a class describing a lambda - /// function object. - bool isLambda() const; - - /// \brief Determine whether this record is a record for captured variables in - /// CapturedStmt construct. - bool isCapturedRecord() const; - /// \brief Mark the record as a record for captured variables in CapturedStmt - /// construct. - void setCapturedRecord(); - - /// getDefinition - Returns the RecordDecl that actually defines - /// this struct/union/class. When determining whether or not a - /// struct/union/class is completely defined, one should use this - /// method as opposed to 'isCompleteDefinition'. - /// 'isCompleteDefinition' indicates whether or not a specific - /// RecordDecl is a completed definition, not whether or not the - /// record type is defined. This method returns NULL if there is - /// no RecordDecl that defines the struct/union/tag. - RecordDecl *getDefinition() const { - return cast_or_null<RecordDecl>(TagDecl::getDefinition()); - } - - // Iterator access to field members. The field iterator only visits - // the non-static data members of this class, ignoring any static - // data members, functions, constructors, destructors, etc. - typedef specific_decl_iterator<FieldDecl> field_iterator; - typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range; - - field_range fields() const { return field_range(field_begin(), field_end()); } - field_iterator field_begin() const; - - field_iterator field_end() const { - return field_iterator(decl_iterator()); - } - - // field_empty - Whether there are any fields (non-static data - // members) in this record. - bool field_empty() const { - return field_begin() == field_end(); - } - - /// completeDefinition - Notes that the definition of this type is - /// now complete. - virtual void completeDefinition(); - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstRecord && K <= lastRecord; - } - - /// isMsStrust - Get whether or not this is an ms_struct which can - /// be turned on with an attribute, pragma, or -mms-bitfields - /// commandline option. - bool isMsStruct(const ASTContext &C) const; - - /// \brief Whether we are allowed to insert extra padding between fields. - /// These padding are added to help AddressSanitizer detect - /// intra-object-overflow bugs. - bool mayInsertExtraPadding(bool EmitRemark = false) const; - - /// Finds the first data member which has a name. - /// nullptr is returned if no named data member exists. - const FieldDecl *findFirstNamedDataMember() const; - -private: - /// \brief Deserialize just the fields. - void LoadFieldsFromExternalStorage() const; -}; - -class FileScopeAsmDecl : public Decl { - virtual void anchor(); - StringLiteral *AsmString; - SourceLocation RParenLoc; - FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, - SourceLocation StartL, SourceLocation EndL) - : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {} -public: - static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, - StringLiteral *Str, SourceLocation AsmLoc, - SourceLocation RParenLoc); - - static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceLocation getAsmLoc() const { return getLocation(); } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(getAsmLoc(), getRParenLoc()); - } - - const StringLiteral *getAsmString() const { return AsmString; } - StringLiteral *getAsmString() { return AsmString; } - void setAsmString(StringLiteral *Asm) { AsmString = Asm; } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == FileScopeAsm; } -}; - -/// BlockDecl - This represents a block literal declaration, which is like an -/// unnamed FunctionDecl. For example: -/// ^{ 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 != nullptr; } - 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; - bool BlockMissingReturnType : 1; - bool IsConversionFromLambda : 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. - ParmVarDecl **ParamInfo; - unsigned NumParams; - - Stmt *Body; - TypeSourceInfo *SignatureAsWritten; - - const Capture *Captures; - unsigned NumCaptures; - - unsigned ManglingNumber; - Decl *ManglingContextDecl; - -protected: - BlockDecl(DeclContext *DC, SourceLocation CaretLoc) - : Decl(Block, DC, CaretLoc), DeclContext(Block), - IsVariadic(false), CapturesCXXThis(false), - BlockMissingReturnType(true), IsConversionFromLambda(false), - ParamInfo(nullptr), NumParams(0), Body(nullptr), - SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0), - ManglingNumber(0), ManglingContextDecl(nullptr) {} - -public: - static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); - static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceLocation getCaretLocation() const { return getLocation(); } - - bool isVariadic() const { return IsVariadic; } - void setIsVariadic(bool value) { IsVariadic = value; } - - CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } - Stmt *getBody() const override { return (Stmt*) Body; } - void setBody(CompoundStmt *B) { Body = (Stmt*) B; } - - void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; } - TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; } - - // Iterator access to formal parameters. - unsigned param_size() const { return getNumParams(); } - typedef ParmVarDecl **param_iterator; - typedef ParmVarDecl * const *param_const_iterator; - typedef llvm::iterator_range<param_iterator> param_range; - typedef llvm::iterator_range<param_const_iterator> param_const_range; - - // ArrayRef access to formal parameters. - // FIXME: Should eventual replace iterator access. - ArrayRef<ParmVarDecl*> parameters() const { - return llvm::makeArrayRef(ParamInfo, param_size()); - } - - bool param_empty() const { return NumParams == 0; } - param_range params() { return param_range(param_begin(), param_end()); } - param_iterator param_begin() { return param_iterator(ParamInfo); } - param_iterator param_end() { - return param_iterator(ParamInfo + param_size()); - } - - param_const_range params() const { - return param_const_range(param_begin(), param_end()); - } - param_const_iterator param_begin() const { - return param_const_iterator(ParamInfo); - } - param_const_iterator param_end() const { - return param_const_iterator(ParamInfo + param_size()); - } - - unsigned getNumParams() const { return NumParams; } - const ParmVarDecl *getParamDecl(unsigned i) const { - assert(i < getNumParams() && "Illegal param #"); - return ParamInfo[i]; - } - ParmVarDecl *getParamDecl(unsigned i) { - assert(i < getNumParams() && "Illegal param #"); - return ParamInfo[i]; - } - void setParams(ArrayRef<ParmVarDecl *> NewParamInfo); - - /// 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; - typedef llvm::iterator_range<capture_iterator> capture_range; - typedef llvm::iterator_range<capture_const_iterator> capture_const_range; - - capture_range captures() { - return capture_range(capture_begin(), capture_end()); - } - capture_const_range captures() const { - return capture_const_range(capture_begin(), capture_end()); - } - - 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; } - bool blockMissingReturnType() const { return BlockMissingReturnType; } - void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; } - - bool isConversionFromLambda() const { return IsConversionFromLambda; } - void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; } - - bool capturesVariable(const VarDecl *var) const; - - void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, - bool CapturesCXXThis); - - unsigned getBlockManglingNumber() const { - return ManglingNumber; - } - Decl *getBlockManglingContextDecl() const { - return ManglingContextDecl; - } - - void setBlockMangling(unsigned Number, Decl *Ctx) { - ManglingNumber = Number; - ManglingContextDecl = Ctx; - } - - SourceRange getSourceRange() const override LLVM_READONLY; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Block; } - static DeclContext *castToDeclContext(const BlockDecl *D) { - return static_cast<DeclContext *>(const_cast<BlockDecl*>(D)); - } - static BlockDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC)); - } -}; - -/// \brief This represents the body of a CapturedStmt, and serves as its -/// DeclContext. -class CapturedDecl final - : public Decl, - public DeclContext, - private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> { -protected: - size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) { - return NumParams; - } - -private: - /// \brief The number of parameters to the outlined function. - unsigned NumParams; - /// \brief The position of context parameter in list of parameters. - unsigned ContextParam; - /// \brief The body of the outlined function. - llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow; - - explicit CapturedDecl(DeclContext *DC, unsigned NumParams); - - ImplicitParamDecl *const *getParams() const { - return getTrailingObjects<ImplicitParamDecl *>(); - } - - ImplicitParamDecl **getParams() { - return getTrailingObjects<ImplicitParamDecl *>(); - } - -public: - static CapturedDecl *Create(ASTContext &C, DeclContext *DC, - unsigned NumParams); - static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumParams); - - Stmt *getBody() const override; - void setBody(Stmt *B); - - bool isNothrow() const; - void setNothrow(bool Nothrow = true); - - unsigned getNumParams() const { return NumParams; } - - ImplicitParamDecl *getParam(unsigned i) const { - assert(i < NumParams); - return getParams()[i]; - } - void setParam(unsigned i, ImplicitParamDecl *P) { - assert(i < NumParams); - getParams()[i] = P; - } - - /// \brief Retrieve the parameter containing captured variables. - ImplicitParamDecl *getContextParam() const { - assert(ContextParam < NumParams); - return getParam(ContextParam); - } - void setContextParam(unsigned i, ImplicitParamDecl *P) { - assert(i < NumParams); - ContextParam = i; - setParam(i, P); - } - unsigned getContextParamPosition() const { return ContextParam; } - - typedef ImplicitParamDecl *const *param_iterator; - typedef llvm::iterator_range<param_iterator> param_range; - - /// \brief Retrieve an iterator pointing to the first parameter decl. - param_iterator param_begin() const { return getParams(); } - /// \brief Retrieve an iterator one past the last parameter decl. - param_iterator param_end() const { return getParams() + NumParams; } - - /// \brief Retrieve an iterator range for the parameter declarations. - param_range params() const { return param_range(param_begin(), param_end()); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Captured; } - static DeclContext *castToDeclContext(const CapturedDecl *D) { - return static_cast<DeclContext *>(const_cast<CapturedDecl *>(D)); - } - static CapturedDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC)); - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; -}; - -/// \brief Describes a module import declaration, which makes the contents -/// of the named module visible in the current translation unit. -/// -/// An import declaration imports the named module (or submodule). For example: -/// \code -/// @import std.vector; -/// \endcode -/// -/// Import declarations can also be implicitly generated from -/// \#include/\#import directives. -class ImportDecl final : public Decl, - llvm::TrailingObjects<ImportDecl, SourceLocation> { - /// \brief The imported module, along with a bit that indicates whether - /// we have source-location information for each identifier in the module - /// name. - /// - /// When the bit is false, we only have a single source location for the - /// end of the import declaration. - llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete; - - /// \brief The next import in the list of imports local to the translation - /// unit being parsed (not loaded from an AST file). - ImportDecl *NextLocalImport; - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTContext; - friend TrailingObjects; - - ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, - ArrayRef<SourceLocation> IdentifierLocs); - - ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, - SourceLocation EndLoc); - - ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { } - -public: - /// \brief Create a new module import declaration. - static ImportDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, Module *Imported, - ArrayRef<SourceLocation> IdentifierLocs); - - /// \brief Create a new module import declaration for an implicitly-generated - /// import. - static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, Module *Imported, - SourceLocation EndLoc); - - /// \brief Create a new, deserialized module import declaration. - static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumLocations); - - /// \brief Retrieve the module that was imported by the import declaration. - Module *getImportedModule() const { return ImportedAndComplete.getPointer(); } - - /// \brief Retrieves the locations of each of the identifiers that make up - /// the complete module name in the import declaration. - /// - /// This will return an empty array if the locations of the individual - /// identifiers aren't available. - ArrayRef<SourceLocation> getIdentifierLocs() const; - - SourceRange getSourceRange() const override LLVM_READONLY; - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Import; } -}; - -/// \brief Represents an empty-declaration. -class EmptyDecl : public Decl { - virtual void anchor(); - EmptyDecl(DeclContext *DC, SourceLocation L) - : Decl(Empty, DC, L) { } - -public: - static EmptyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L); - static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Empty; } -}; - -/// Insertion operator for diagnostics. This allows sending NamedDecl's -/// into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const NamedDecl* ND) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), - DiagnosticsEngine::ak_nameddecl); - return DB; -} -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const NamedDecl* ND) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND), - DiagnosticsEngine::ak_nameddecl); - return PD; -} - -template<typename decl_type> -void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { - // Note: This routine is implemented here because we need both NamedDecl - // and Redeclarable to be defined. - assert(RedeclLink.NextIsLatest() && - "setPreviousDecl on a decl already in a redeclaration chain"); - - 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. - First = PrevDecl->getFirstDecl(); - assert(First->RedeclLink.NextIsLatest() && "Expected first"); - decl_type *MostRecent = First->getNextRedeclaration(); - RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent)); - - // If the declaration was previously visible, a redeclaration of it remains - // visible even if it wouldn't be visible by itself. - static_cast<decl_type*>(this)->IdentifierNamespace |= - MostRecent->getIdentifierNamespace() & - (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); - } else { - // Make this first. - First = static_cast<decl_type*>(this); - } - - // First one will point to this one as latest. - First->RedeclLink.setLatest(static_cast<decl_type*>(this)); - - assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) || - cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid()); -} - -// Inline function definitions. - -/// \brief Check if the given decl is complete. -/// -/// We use this function to break a cycle between the inline definitions in -/// Type.h and Decl.h. -inline bool IsEnumDeclComplete(EnumDecl *ED) { - return ED->isComplete(); -} - -/// \brief Check if the given decl is scoped. -/// -/// We use this function to break a cycle between the inline definitions in -/// Type.h and Decl.h. -inline bool IsEnumDeclScoped(EnumDecl *ED) { - return ED->isScoped(); -} - -} // end namespace clang - -#endif diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h deleted file mode 100644 index 3c5056c..0000000 --- a/include/clang/AST/DeclAccessPair.h +++ /dev/null @@ -1,72 +0,0 @@ -//===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 DeclAccessPair class, which provides an -// efficient representation of a pair of a NamedDecl* and an -// AccessSpecifier. Generally the access specifier gives the -// natural access of a declaration when named in a class, as -// defined in C++ [class.access.base]p1. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H -#define LLVM_CLANG_AST_DECLACCESSPAIR_H - -#include "clang/Basic/Specifiers.h" -#include "llvm/Support/DataTypes.h" - -namespace clang { - -class NamedDecl; - -/// A POD class for pairing a NamedDecl* with an access specifier. -/// Can be put into unions. -class DeclAccessPair { - uintptr_t Ptr; // we'd use llvm::PointerUnion, but it isn't trivial - - enum { Mask = 0x3 }; - -public: - static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { - DeclAccessPair p; - p.set(D, AS); - return p; - } - - NamedDecl *getDecl() const { - return reinterpret_cast<NamedDecl*>(~Mask & Ptr); - } - AccessSpecifier getAccess() const { - return AccessSpecifier(Mask & Ptr); - } - - void setDecl(NamedDecl *D) { - set(D, getAccess()); - } - void setAccess(AccessSpecifier AS) { - set(getDecl(), AS); - } - void set(NamedDecl *D, AccessSpecifier AS) { - Ptr = uintptr_t(AS) | reinterpret_cast<uintptr_t>(D); - } - - operator NamedDecl*() const { return getDecl(); } - NamedDecl *operator->() const { return getDecl(); } -}; -} - -// Take a moment to tell SmallVector that DeclAccessPair is POD. -namespace llvm { -template<typename> struct isPodLike; -template<> struct isPodLike<clang::DeclAccessPair> { - static const bool value = true; -}; -} - -#endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h deleted file mode 100644 index 05b2a12..0000000 --- a/include/clang/AST/DeclBase.h +++ /dev/null @@ -1,1904 +0,0 @@ -//===-- DeclBase.h - Base Classes for representing declarations -*- 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 Decl and DeclContext interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLBASE_H -#define LLVM_CLANG_AST_DECLBASE_H - -#include "clang/AST/AttrIterator.h" -#include "clang/AST/DeclarationName.h" -#include "clang/Basic/Specifiers.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/PrettyStackTrace.h" - -namespace clang { -class ASTMutationListener; -class BlockDecl; -class CXXRecordDecl; -class CompoundStmt; -class DeclContext; -class DeclarationName; -class DependentDiagnostic; -class EnumDecl; -class FunctionDecl; -class FunctionType; -enum Linkage : unsigned char; -class LinkageComputer; -class LinkageSpecDecl; -class Module; -class NamedDecl; -class NamespaceDecl; -class ObjCCategoryDecl; -class ObjCCategoryImplDecl; -class ObjCContainerDecl; -class ObjCImplDecl; -class ObjCImplementationDecl; -class ObjCInterfaceDecl; -class ObjCMethodDecl; -class ObjCProtocolDecl; -struct PrintingPolicy; -class RecordDecl; -class Stmt; -class StoredDeclsMap; -class TranslationUnitDecl; -class UsingDirectiveDecl; -} - -namespace clang { - - /// \brief Captures the result of checking the availability of a - /// declaration. - enum AvailabilityResult { - AR_Available = 0, - AR_NotYetIntroduced, - AR_Deprecated, - AR_Unavailable - }; - -/// Decl - This represents one declaration (or definition), e.g. a variable, -/// typedef, function, struct, etc. -/// -/// Note: There are objects tacked on before the *beginning* of Decl -/// (and its subclasses) in its Decl::operator new(). Proper alignment -/// of all subclasses (not requiring more than DeclObjAlignment) is -/// asserted in DeclBase.cpp. -class Decl { -public: - /// \brief Alignment guaranteed when allocating Decl and any subtypes. - enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment }; - - /// \brief Lists the kind of concrete classes of Decl. - enum Kind { -#define DECL(DERIVED, BASE) DERIVED, -#define ABSTRACT_DECL(DECL) -#define DECL_RANGE(BASE, START, END) \ - first##BASE = START, last##BASE = END, -#define LAST_DECL_RANGE(BASE, START, END) \ - first##BASE = START, last##BASE = END -#include "clang/AST/DeclNodes.inc" - }; - - /// \brief A placeholder type used to construct an empty shell of a - /// decl-derived type that will be filled in later (e.g., by some - /// deserialization method). - struct EmptyShell { }; - - /// IdentifierNamespace - The different namespaces in which - /// declarations may appear. According to C99 6.2.3, there are - /// four namespaces, labels, tags, members and ordinary - /// identifiers. C++ describes lookup completely differently: - /// certain lookups merely "ignore" certain kinds of declarations, - /// usually based on whether the declaration is of a type, etc. - /// - /// These are meant as bitmasks, so that searches in - /// C++ can look into the "tag" namespace during ordinary lookup. - /// - /// Decl currently provides 15 bits of IDNS bits. - enum IdentifierNamespace { - /// Labels, declared with 'x:' and referenced with 'goto x'. - IDNS_Label = 0x0001, - - /// Tags, declared with 'struct foo;' and referenced with - /// 'struct foo'. All tags are also types. This is what - /// elaborated-type-specifiers look for in C. - IDNS_Tag = 0x0002, - - /// Types, declared with 'struct foo', typedefs, etc. - /// This is what elaborated-type-specifiers look for in C++, - /// but note that it's ill-formed to find a non-tag. - IDNS_Type = 0x0004, - - /// Members, declared with object declarations within tag - /// definitions. In C, these can only be found by "qualified" - /// lookup in member expressions. In C++, they're found by - /// normal lookup. - IDNS_Member = 0x0008, - - /// Namespaces, declared with 'namespace foo {}'. - /// Lookup for nested-name-specifiers find these. - IDNS_Namespace = 0x0010, - - /// Ordinary names. In C, everything that's not a label, tag, - /// or member ends up here. - IDNS_Ordinary = 0x0020, - - /// Objective C \@protocol. - IDNS_ObjCProtocol = 0x0040, - - /// This declaration is a friend function. A friend function - /// declaration is always in this namespace but may also be in - /// IDNS_Ordinary if it was previously declared. - IDNS_OrdinaryFriend = 0x0080, - - /// This declaration is a friend class. A friend class - /// declaration is always in this namespace but may also be in - /// IDNS_Tag|IDNS_Type if it was previously declared. - IDNS_TagFriend = 0x0100, - - /// This declaration is a using declaration. A using declaration - /// *introduces* a number of other declarations into the current - /// scope, and those declarations use the IDNS of their targets, - /// but the actual using declarations go in this namespace. - IDNS_Using = 0x0200, - - /// This declaration is a C++ operator declared in a non-class - /// context. All such operators are also in IDNS_Ordinary. - /// C++ lexical operator lookup looks for these. - IDNS_NonMemberOperator = 0x0400, - - /// This declaration is a function-local extern declaration of a - /// variable or function. This may also be IDNS_Ordinary if it - /// has been declared outside any function. - IDNS_LocalExtern = 0x0800 - }; - - /// ObjCDeclQualifier - 'Qualifiers' written next to the return and - /// parameter types in method declarations. Other than remembering - /// them and mangling them into the method's signature string, these - /// are ignored by the compiler; they are consumed by certain - /// remote-messaging frameworks. - /// - /// in, inout, and out are mutually exclusive and apply only to - /// method parameters. bycopy and byref are mutually exclusive and - /// apply only to method parameters (?). oneway applies only to - /// results. All of these expect their corresponding parameter to - /// have a particular type. None of this is currently enforced by - /// clang. - /// - /// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier. - enum ObjCDeclQualifier { - OBJC_TQ_None = 0x0, - OBJC_TQ_In = 0x1, - OBJC_TQ_Inout = 0x2, - OBJC_TQ_Out = 0x4, - OBJC_TQ_Bycopy = 0x8, - OBJC_TQ_Byref = 0x10, - OBJC_TQ_Oneway = 0x20, - - /// The nullability qualifier is set when the nullability of the - /// result or parameter was expressed via a context-sensitive - /// keyword. - OBJC_TQ_CSNullability = 0x40 - }; - -protected: - // Enumeration values used in the bits stored in NextInContextAndBits. - enum { - /// \brief Whether this declaration is a top-level declaration (function, - /// global variable, etc.) that is lexically inside an objc container - /// definition. - TopLevelDeclInObjCContainerFlag = 0x01, - - /// \brief Whether this declaration is private to the module in which it was - /// defined. - ModulePrivateFlag = 0x02 - }; - - /// \brief The next declaration within the same lexical - /// DeclContext. These pointers form the linked list that is - /// traversed via DeclContext's decls_begin()/decls_end(). - /// - /// The extra two bits are used for the TopLevelDeclInObjCContainer and - /// ModulePrivate bits. - llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits; - -private: - friend class DeclContext; - - struct MultipleDC { - DeclContext *SemanticDC; - DeclContext *LexicalDC; - }; - - - /// DeclCtx - Holds either a DeclContext* or a MultipleDC*. - /// For declarations that don't contain C++ scope specifiers, it contains - /// the DeclContext where the Decl was declared. - /// For declarations with C++ scope specifiers, it contains a MultipleDC* - /// with the context where it semantically belongs (SemanticDC) and the - /// context where it was lexically declared (LexicalDC). - /// e.g.: - /// - /// namespace A { - /// void f(); // SemanticDC == LexicalDC == 'namespace A' - /// } - /// void A::f(); // SemanticDC == namespace 'A' - /// // LexicalDC == global namespace - llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx; - - inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } - inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } - inline MultipleDC *getMultipleDC() const { - return DeclCtx.get<MultipleDC*>(); - } - inline DeclContext *getSemanticDC() const { - return DeclCtx.get<DeclContext*>(); - } - - /// Loc - The location of this decl. - SourceLocation Loc; - - /// DeclKind - This indicates which class this is. - unsigned DeclKind : 8; - - /// InvalidDecl - This indicates a semantic error occurred. - unsigned InvalidDecl : 1; - - /// HasAttrs - This indicates whether the decl has attributes or not. - unsigned HasAttrs : 1; - - /// Implicit - Whether this declaration was implicitly generated by - /// the implementation rather than explicitly written by the user. - unsigned Implicit : 1; - - /// \brief Whether this declaration was "used", meaning that a definition is - /// required. - unsigned Used : 1; - - /// \brief Whether this declaration was "referenced". - /// The difference with 'Used' is whether the reference appears in a - /// evaluated context or not, e.g. functions used in uninstantiated templates - /// are regarded as "referenced" but not "used". - unsigned Referenced : 1; - - /// \brief Whether statistic collection is enabled. - static bool StatisticsEnabled; - -protected: - /// Access - Used by C++ decls for the access specifier. - // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum - unsigned Access : 2; - friend class CXXClassMemberWrapper; - - /// \brief Whether this declaration was loaded from an AST file. - unsigned FromASTFile : 1; - - /// \brief Whether this declaration is hidden from normal name lookup, e.g., - /// because it is was loaded from an AST file is either module-private or - /// because its submodule has not been made visible. - unsigned Hidden : 1; - - /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. - unsigned IdentifierNamespace : 12; - - /// \brief If 0, we have not computed the linkage of this declaration. - /// Otherwise, it is the linkage + 1. - mutable unsigned CacheValidAndLinkage : 3; - - friend class ASTDeclWriter; - friend class ASTDeclReader; - friend class ASTReader; - friend class LinkageComputer; - - template<typename decl_type> friend class Redeclarable; - - /// \brief Allocate memory for a deserialized declaration. - /// - /// This routine must be used to allocate memory for any declaration that is - /// deserialized from a module file. - /// - /// \param Size The size of the allocated object. - /// \param Ctx The context in which we will allocate memory. - /// \param ID The global ID of the deserialized declaration. - /// \param Extra The amount of extra space to allocate after the object. - void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID, - std::size_t Extra = 0); - - /// \brief Allocate memory for a non-deserialized declaration. - void *operator new(std::size_t Size, const ASTContext &Ctx, - DeclContext *Parent, std::size_t Extra = 0); - -private: - bool AccessDeclContextSanity() const; - -protected: - - Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextInContextAndBits(), DeclCtx(DC), - Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), Hidden(DC && cast<Decl>(DC)->Hidden), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) - { - if (StatisticsEnabled) add(DK); - } - - Decl(Kind DK, EmptyShell Empty) - : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), Hidden(0), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) - { - if (StatisticsEnabled) add(DK); - } - - virtual ~Decl(); - - /// \brief Update a potentially out-of-date declaration. - void updateOutOfDate(IdentifierInfo &II) const; - - Linkage getCachedLinkage() const { - return Linkage(CacheValidAndLinkage - 1); - } - - void setCachedLinkage(Linkage L) const { - CacheValidAndLinkage = L + 1; - } - - bool hasCachedLinkage() const { - return CacheValidAndLinkage; - } - -public: - - /// \brief Source range that this declaration covers. - virtual SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocation(), getLocation()); - } - SourceLocation getLocStart() const LLVM_READONLY { - return getSourceRange().getBegin(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSourceRange().getEnd(); - } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - Kind getKind() const { return static_cast<Kind>(DeclKind); } - const char *getDeclKindName() const; - - Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); } - const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();} - - DeclContext *getDeclContext() { - if (isInSemaDC()) - return getSemanticDC(); - return getMultipleDC()->SemanticDC; - } - const DeclContext *getDeclContext() const { - return const_cast<Decl*>(this)->getDeclContext(); - } - - /// Find the innermost non-closure ancestor of this declaration, - /// walking up through blocks, lambdas, etc. If that ancestor is - /// not a code context (!isFunctionOrMethod()), returns null. - /// - /// A declaration may be its own non-closure context. - Decl *getNonClosureContext(); - const Decl *getNonClosureContext() const { - return const_cast<Decl*>(this)->getNonClosureContext(); - } - - TranslationUnitDecl *getTranslationUnitDecl(); - const TranslationUnitDecl *getTranslationUnitDecl() const { - return const_cast<Decl*>(this)->getTranslationUnitDecl(); - } - - bool isInAnonymousNamespace() const; - - bool isInStdNamespace() const; - - ASTContext &getASTContext() const LLVM_READONLY; - - void setAccess(AccessSpecifier AS) { - Access = AS; - assert(AccessDeclContextSanity()); - } - - AccessSpecifier getAccess() const { - assert(AccessDeclContextSanity()); - return AccessSpecifier(Access); - } - - /// \brief Retrieve the access specifier for this declaration, even though - /// it may not yet have been properly set. - AccessSpecifier getAccessUnsafe() const { - return AccessSpecifier(Access); - } - - bool hasAttrs() const { return HasAttrs; } - void setAttrs(const AttrVec& Attrs) { - return setAttrsImpl(Attrs, getASTContext()); - } - AttrVec &getAttrs() { - return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); - } - const AttrVec &getAttrs() const; - void dropAttrs(); - - void addAttr(Attr *A) { - if (hasAttrs()) - getAttrs().push_back(A); - else - setAttrs(AttrVec(1, A)); - } - - typedef AttrVec::const_iterator attr_iterator; - typedef llvm::iterator_range<attr_iterator> attr_range; - - attr_range attrs() const { - return attr_range(attr_begin(), attr_end()); - } - - attr_iterator attr_begin() const { - return hasAttrs() ? getAttrs().begin() : nullptr; - } - attr_iterator attr_end() const { - return hasAttrs() ? getAttrs().end() : nullptr; - } - - template <typename T> - void dropAttr() { - if (!HasAttrs) return; - - AttrVec &Vec = getAttrs(); - Vec.erase(std::remove_if(Vec.begin(), Vec.end(), isa<T, Attr*>), Vec.end()); - - if (Vec.empty()) - HasAttrs = false; - } - - template <typename T> - llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const { - return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>()); - } - - template <typename T> - specific_attr_iterator<T> specific_attr_begin() const { - return specific_attr_iterator<T>(attr_begin()); - } - template <typename T> - specific_attr_iterator<T> specific_attr_end() const { - return specific_attr_iterator<T>(attr_end()); - } - - template<typename T> T *getAttr() const { - return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : nullptr; - } - template<typename T> bool hasAttr() const { - return hasAttrs() && hasSpecificAttr<T>(getAttrs()); - } - - /// getMaxAlignment - return the maximum alignment specified by attributes - /// on this decl, 0 if there are none. - unsigned getMaxAlignment() const; - - /// setInvalidDecl - Indicates the Decl had a semantic error. This - /// allows for graceful error recovery. - void setInvalidDecl(bool Invalid = true); - bool isInvalidDecl() const { return (bool) InvalidDecl; } - - /// isImplicit - Indicates whether the declaration was implicitly - /// generated by the implementation. If false, this declaration - /// was written explicitly in the source code. - bool isImplicit() const { return Implicit; } - void setImplicit(bool I = true) { Implicit = I; } - - /// \brief Whether this declaration was used, meaning that a definition - /// is required. - /// - /// \param CheckUsedAttr When true, also consider the "used" attribute - /// (in addition to the "used" bit set by \c setUsed()) when determining - /// whether the function is used. - bool isUsed(bool CheckUsedAttr = true) const; - - /// \brief Set whether the declaration is used, in the sense of odr-use. - /// - /// This should only be used immediately after creating a declaration. - void setIsUsed() { Used = true; } - - /// \brief Mark the declaration used, in the sense of odr-use. - /// - /// This notifies any mutation listeners in addition to setting a bit - /// indicating the declaration is used. - void markUsed(ASTContext &C); - - /// \brief Whether any declaration of this entity was referenced. - bool isReferenced() const; - - /// \brief Whether this declaration was referenced. This should not be relied - /// upon for anything other than debugging. - bool isThisDeclarationReferenced() const { return Referenced; } - - void setReferenced(bool R = true) { Referenced = R; } - - /// \brief Whether this declaration is a top-level declaration (function, - /// global variable, etc.) that is lexically inside an objc container - /// definition. - bool isTopLevelDeclInObjCContainer() const { - return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag; - } - - void setTopLevelDeclInObjCContainer(bool V = true) { - unsigned Bits = NextInContextAndBits.getInt(); - if (V) - Bits |= TopLevelDeclInObjCContainerFlag; - else - Bits &= ~TopLevelDeclInObjCContainerFlag; - NextInContextAndBits.setInt(Bits); - } - - /// \brief Whether this declaration was marked as being private to the - /// module in which it was defined. - bool isModulePrivate() const { - return NextInContextAndBits.getInt() & ModulePrivateFlag; - } - -protected: - /// \brief Specify whether this declaration was marked as being private - /// to the module in which it was defined. - void setModulePrivate(bool MP = true) { - unsigned Bits = NextInContextAndBits.getInt(); - if (MP) - Bits |= ModulePrivateFlag; - else - Bits &= ~ModulePrivateFlag; - NextInContextAndBits.setInt(Bits); - } - - /// \brief Set the owning module ID. - void setOwningModuleID(unsigned ID) { - assert(isFromASTFile() && "Only works on a deserialized declaration"); - *((unsigned*)this - 2) = ID; - } - -public: - - /// \brief Determine the availability of the given declaration. - /// - /// This routine will determine the most restrictive availability of - /// the given declaration (e.g., preferring 'unavailable' to - /// 'deprecated'). - /// - /// \param Message If non-NULL and the result is not \c - /// AR_Available, will be set to a (possibly empty) message - /// describing why the declaration has not been introduced, is - /// deprecated, or is unavailable. - AvailabilityResult getAvailability(std::string *Message = nullptr) const; - - /// \brief Determine whether this declaration is marked 'deprecated'. - /// - /// \param Message If non-NULL and the declaration is deprecated, - /// this will be set to the message describing why the declaration - /// was deprecated (which may be empty). - bool isDeprecated(std::string *Message = nullptr) const { - return getAvailability(Message) == AR_Deprecated; - } - - /// \brief Determine whether this declaration is marked 'unavailable'. - /// - /// \param Message If non-NULL and the declaration is unavailable, - /// this will be set to the message describing why the declaration - /// was made unavailable (which may be empty). - bool isUnavailable(std::string *Message = nullptr) const { - return getAvailability(Message) == AR_Unavailable; - } - - /// \brief Determine whether this is a weak-imported symbol. - /// - /// Weak-imported symbols are typically marked with the - /// 'weak_import' attribute, but may also be marked with an - /// 'availability' attribute where we're targing a platform prior to - /// the introduction of this feature. - bool isWeakImported() const; - - /// \brief Determines whether this symbol can be weak-imported, - /// e.g., whether it would be well-formed to add the weak_import - /// attribute. - /// - /// \param IsDefinition Set to \c true to indicate that this - /// declaration cannot be weak-imported because it has a definition. - bool canBeWeakImported(bool &IsDefinition) const; - - /// \brief Determine whether this declaration came from an AST file (such as - /// a precompiled header or module) rather than having been parsed. - bool isFromASTFile() const { return FromASTFile; } - - /// \brief Retrieve the global declaration ID associated with this - /// declaration, which specifies where in the - unsigned getGlobalID() const { - if (isFromASTFile()) - return *((const unsigned*)this - 1); - return 0; - } - - /// \brief Retrieve the global ID of the module that owns this particular - /// declaration. - unsigned getOwningModuleID() const { - if (isFromASTFile()) - return *((const unsigned*)this - 2); - - return 0; - } - -private: - Module *getOwningModuleSlow() const; -protected: - bool hasLocalOwningModuleStorage() const; - -public: - /// \brief Get the imported owning module, if this decl is from an imported - /// (non-local) module. - Module *getImportedOwningModule() const { - if (!isFromASTFile()) - return nullptr; - - return getOwningModuleSlow(); - } - - /// \brief Get the local owning module, if known. Returns nullptr if owner is - /// not yet known or declaration is not from a module. - Module *getLocalOwningModule() const { - if (isFromASTFile() || !Hidden) - return nullptr; - return reinterpret_cast<Module *const *>(this)[-1]; - } - void setLocalOwningModule(Module *M) { - assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() && - "should not have a cached owning module"); - reinterpret_cast<Module **>(this)[-1] = M; - } - - unsigned getIdentifierNamespace() const { - return IdentifierNamespace; - } - bool isInIdentifierNamespace(unsigned NS) const { - return getIdentifierNamespace() & NS; - } - static unsigned getIdentifierNamespaceForKind(Kind DK); - - bool hasTagIdentifierNamespace() const { - return isTagIdentifierNamespace(getIdentifierNamespace()); - } - static bool isTagIdentifierNamespace(unsigned NS) { - // TagDecls have Tag and Type set and may also have TagFriend. - return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type); - } - - /// getLexicalDeclContext - The declaration context where this Decl was - /// lexically declared (LexicalDC). May be different from - /// getDeclContext() (SemanticDC). - /// e.g.: - /// - /// namespace A { - /// void f(); // SemanticDC == LexicalDC == 'namespace A' - /// } - /// void A::f(); // SemanticDC == namespace 'A' - /// // LexicalDC == global namespace - DeclContext *getLexicalDeclContext() { - if (isInSemaDC()) - return getSemanticDC(); - return getMultipleDC()->LexicalDC; - } - const DeclContext *getLexicalDeclContext() const { - return const_cast<Decl*>(this)->getLexicalDeclContext(); - } - - /// Determine whether this declaration is declared out of line (outside its - /// semantic context). - virtual bool isOutOfLine() const; - - /// setDeclContext - Set both the semantic and lexical DeclContext - /// to DC. - void setDeclContext(DeclContext *DC); - - void setLexicalDeclContext(DeclContext *DC); - - /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this - /// scoped decl is defined outside the current function or method. This is - /// roughly global variables and functions, but also handles enums (which - /// could be defined inside or outside a function etc). - bool isDefinedOutsideFunctionOrMethod() const { - return getParentFunctionOrMethod() == nullptr; - } - - /// \brief Returns true if this declaration lexically is inside a function. - /// It recognizes non-defining declarations as well as members of local - /// classes: - /// \code - /// void foo() { void bar(); } - /// void foo2() { class ABC { void bar(); }; } - /// \endcode - bool isLexicallyWithinFunctionOrMethod() const; - - /// \brief If this decl is defined inside a function/method/block it returns - /// the corresponding DeclContext, otherwise it returns null. - const DeclContext *getParentFunctionOrMethod() const; - DeclContext *getParentFunctionOrMethod() { - return const_cast<DeclContext*>( - const_cast<const Decl*>(this)->getParentFunctionOrMethod()); - } - - /// \brief Retrieves the "canonical" declaration of the given declaration. - virtual Decl *getCanonicalDecl() { return this; } - const Decl *getCanonicalDecl() const { - return const_cast<Decl*>(this)->getCanonicalDecl(); - } - - /// \brief Whether this particular Decl is a canonical one. - bool isCanonicalDecl() const { return getCanonicalDecl() == this; } - -protected: - /// \brief Returns the next redeclaration or itself if this is the only decl. - /// - /// Decl subclasses that can be redeclared should override this method so that - /// Decl::redecl_iterator can iterate over them. - virtual Decl *getNextRedeclarationImpl() { return this; } - - /// \brief Implementation of getPreviousDecl(), to be overridden by any - /// subclass that has a redeclaration chain. - virtual Decl *getPreviousDeclImpl() { return nullptr; } - - /// \brief Implementation of getMostRecentDecl(), to be overridden by any - /// subclass that has a redeclaration chain. - virtual Decl *getMostRecentDeclImpl() { return this; } - -public: - /// \brief Iterates through all the redeclarations of the same decl. - class redecl_iterator { - /// Current - The current declaration. - Decl *Current; - Decl *Starter; - - public: - typedef Decl *value_type; - typedef const value_type &reference; - typedef const value_type *pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - redecl_iterator() : Current(nullptr) { } - explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } - - reference operator*() const { return Current; } - value_type operator->() const { return Current; } - - redecl_iterator& operator++() { - assert(Current && "Advancing while iterator has reached end"); - // Get either previous decl or latest decl. - Decl *Next = Current->getNextRedeclarationImpl(); - assert(Next && "Should return next redeclaration or itself, never null!"); - Current = (Next != Starter) ? Next : nullptr; - return *this; - } - - redecl_iterator operator++(int) { - redecl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(redecl_iterator x, redecl_iterator y) { - return x.Current == y.Current; - } - friend bool operator!=(redecl_iterator x, redecl_iterator y) { - return x.Current != y.Current; - } - }; - - typedef llvm::iterator_range<redecl_iterator> redecl_range; - - /// \brief Returns an iterator range for all the redeclarations of the same - /// decl. It will iterate at least once (when this decl is the only one). - redecl_range redecls() const { - return redecl_range(redecls_begin(), redecls_end()); - } - - redecl_iterator redecls_begin() const { - return redecl_iterator(const_cast<Decl *>(this)); - } - redecl_iterator redecls_end() const { return redecl_iterator(); } - - /// \brief Retrieve the previous declaration that declares the same entity - /// as this declaration, or NULL if there is no previous declaration. - Decl *getPreviousDecl() { return getPreviousDeclImpl(); } - - /// \brief Retrieve the most recent declaration that declares the same entity - /// as this declaration, or NULL if there is no previous declaration. - const Decl *getPreviousDecl() const { - return const_cast<Decl *>(this)->getPreviousDeclImpl(); - } - - /// \brief True if this is the first declaration in its redeclaration chain. - bool isFirstDecl() const { - return getPreviousDecl() == nullptr; - } - - /// \brief Retrieve the most recent declaration that declares the same entity - /// as this declaration (which may be this declaration). - Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } - - /// \brief Retrieve the most recent declaration that declares the same entity - /// as this declaration (which may be this declaration). - const Decl *getMostRecentDecl() const { - return const_cast<Decl *>(this)->getMostRecentDeclImpl(); - } - - /// getBody - If this Decl represents a declaration for a body of code, - /// such as a function or method definition, this method returns the - /// top-level Stmt* of that body. Otherwise this method returns null. - virtual Stmt* getBody() const { return nullptr; } - - /// \brief Returns true if this \c Decl represents a declaration for a body of - /// code, such as a function or method definition. - /// Note that \c hasBody can also return true if any redeclaration of this - /// \c Decl represents a declaration for a body of code. - virtual bool hasBody() const { return getBody() != nullptr; } - - /// getBodyRBrace - Gets the right brace of the body, if a body exists. - /// This works whether the body is a CompoundStmt or a CXXTryStmt. - SourceLocation getBodyRBrace() const; - - // global temp stats (until we have a per-module visitor) - static void add(Kind k); - static void EnableStatistics(); - static void PrintStats(); - - /// isTemplateParameter - Determines whether this declaration is a - /// template parameter. - bool isTemplateParameter() const; - - /// isTemplateParameter - Determines whether this declaration is a - /// template parameter pack. - bool isTemplateParameterPack() const; - - /// \brief Whether this declaration is a parameter pack. - bool isParameterPack() const; - - /// \brief returns true if this declaration is a template - bool isTemplateDecl() const; - - /// \brief Whether this declaration is a function or function template. - bool isFunctionOrFunctionTemplate() const { - return (DeclKind >= Decl::firstFunction && - DeclKind <= Decl::lastFunction) || - DeclKind == FunctionTemplate; - } - - /// \brief Returns the function itself, or the templated function if this is a - /// function template. - FunctionDecl *getAsFunction() LLVM_READONLY; - - const FunctionDecl *getAsFunction() const { - return const_cast<Decl *>(this)->getAsFunction(); - } - - /// \brief Changes the namespace of this declaration to reflect that it's - /// a function-local extern declaration. - /// - /// These declarations appear in the lexical context of the extern - /// declaration, but in the semantic context of the enclosing namespace - /// scope. - void setLocalExternDecl() { - assert((IdentifierNamespace == IDNS_Ordinary || - IdentifierNamespace == IDNS_OrdinaryFriend) && - "namespace is not ordinary"); - - Decl *Prev = getPreviousDecl(); - IdentifierNamespace &= ~IDNS_Ordinary; - - IdentifierNamespace |= IDNS_LocalExtern; - if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary) - IdentifierNamespace |= IDNS_Ordinary; - } - - /// \brief Determine whether this is a block-scope declaration with linkage. - /// This will either be a local variable declaration declared 'extern', or a - /// local function declaration. - bool isLocalExternDecl() { - return IdentifierNamespace & IDNS_LocalExtern; - } - - /// \brief Changes the namespace of this declaration to reflect that it's - /// the object of a friend declaration. - /// - /// These declarations appear in the lexical context of the friending - /// class, but in the semantic context of the actual entity. This property - /// applies only to a specific decl object; other redeclarations of the - /// same entity may not (and probably don't) share this property. - void setObjectOfFriendDecl(bool PerformFriendInjection = false) { - unsigned OldNS = IdentifierNamespace; - assert((OldNS & (IDNS_Tag | IDNS_Ordinary | - IDNS_TagFriend | IDNS_OrdinaryFriend | - IDNS_LocalExtern)) && - "namespace includes neither ordinary nor tag"); - assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | - IDNS_TagFriend | IDNS_OrdinaryFriend | - IDNS_LocalExtern)) && - "namespace includes other than ordinary or tag"); - - Decl *Prev = getPreviousDecl(); - IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type); - - if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { - IdentifierNamespace |= IDNS_TagFriend; - if (PerformFriendInjection || - (Prev && Prev->getIdentifierNamespace() & IDNS_Tag)) - IdentifierNamespace |= IDNS_Tag | IDNS_Type; - } - - if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) { - IdentifierNamespace |= IDNS_OrdinaryFriend; - if (PerformFriendInjection || - (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)) - IdentifierNamespace |= IDNS_Ordinary; - } - } - - enum FriendObjectKind { - FOK_None, ///< Not a friend object. - FOK_Declared, ///< A friend of a previously-declared entity. - FOK_Undeclared ///< A friend of a previously-undeclared entity. - }; - - /// \brief Determines whether this declaration is the object of a - /// friend declaration and, if so, what kind. - /// - /// There is currently no direct way to find the associated FriendDecl. - FriendObjectKind getFriendObjectKind() const { - unsigned mask = - (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); - if (!mask) return FOK_None; - return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared - : FOK_Undeclared); - } - - /// Specifies that this declaration is a C++ overloaded non-member. - void setNonMemberOperator() { - assert(getKind() == Function || getKind() == FunctionTemplate); - assert((IdentifierNamespace & IDNS_Ordinary) && - "visible non-member operators should be in ordinary namespace"); - IdentifierNamespace |= IDNS_NonMemberOperator; - } - - static bool classofKind(Kind K) { return true; } - static DeclContext *castToDeclContext(const Decl *); - static Decl *castFromDeclContext(const DeclContext *); - - void print(raw_ostream &Out, unsigned Indentation = 0, - bool PrintInstantiation = false) const; - void print(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0, bool PrintInstantiation = false) const; - static void printGroup(Decl** Begin, unsigned NumDecls, - raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0); - // Debuggers don't usually respect default arguments. - void dump() const; - // Same as dump(), but forces color printing. - void dumpColor() const; - void dump(raw_ostream &Out) const; - - /// \brief Looks through the Decl's underlying type to extract a FunctionType - /// when possible. Will return null if the type underlying the Decl does not - /// have a FunctionType. - const FunctionType *getFunctionType(bool BlocksToo = true) const; - -private: - void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); - void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, - ASTContext &Ctx); - -protected: - ASTMutationListener *getASTMutationListener() const; -}; - -/// \brief Determine whether two declarations declare the same entity. -inline bool declaresSameEntity(const Decl *D1, const Decl *D2) { - if (!D1 || !D2) - return false; - - if (D1 == D2) - return true; - - return D1->getCanonicalDecl() == D2->getCanonicalDecl(); -} - -/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when -/// doing something to a specific decl. -class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { - const Decl *TheDecl; - SourceLocation Loc; - SourceManager &SM; - const char *Message; -public: - PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L, - SourceManager &sm, const char *Msg) - : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} - - void print(raw_ostream &OS) const override; -}; - -/// \brief The results of name lookup within a DeclContext. This is either a -/// single result (with no stable storage) or a collection of results (with -/// stable storage provided by the lookup table). -class DeclContextLookupResult { - typedef ArrayRef<NamedDecl *> ResultTy; - ResultTy Result; - // If there is only one lookup result, it would be invalidated by - // reallocations of the name table, so store it separately. - NamedDecl *Single; - - static NamedDecl *const SingleElementDummyList; - -public: - DeclContextLookupResult() : Result(), Single() {} - DeclContextLookupResult(ArrayRef<NamedDecl *> Result) - : Result(Result), Single() {} - DeclContextLookupResult(NamedDecl *Single) - : Result(SingleElementDummyList), Single(Single) {} - - class iterator; - typedef llvm::iterator_adaptor_base<iterator, ResultTy::iterator, - std::random_access_iterator_tag, - NamedDecl *const> IteratorBase; - class iterator : public IteratorBase { - value_type SingleElement; - - public: - iterator() : IteratorBase(), SingleElement() {} - explicit iterator(pointer Pos, value_type Single = nullptr) - : IteratorBase(Pos), SingleElement(Single) {} - - reference operator*() const { - return SingleElement ? SingleElement : IteratorBase::operator*(); - } - }; - typedef iterator const_iterator; - typedef iterator::pointer pointer; - typedef iterator::reference reference; - - iterator begin() const { return iterator(Result.begin(), Single); } - iterator end() const { return iterator(Result.end(), Single); } - - bool empty() const { return Result.empty(); } - pointer data() const { return Single ? &Single : Result.data(); } - size_t size() const { return Single ? 1 : Result.size(); } - reference front() const { return Single ? Single : Result.front(); } - reference back() const { return Single ? Single : Result.back(); } - reference operator[](size_t N) const { return Single ? Single : Result[N]; } - - // FIXME: Remove this from the interface - DeclContextLookupResult slice(size_t N) const { - DeclContextLookupResult Sliced = Result.slice(N); - Sliced.Single = Single; - return Sliced; - } -}; - -/// DeclContext - This is used only as base class of specific decl types that -/// can act as declaration contexts. These decls are (only the top classes -/// that directly derive from DeclContext are mentioned, not their subclasses): -/// -/// TranslationUnitDecl -/// NamespaceDecl -/// FunctionDecl -/// TagDecl -/// ObjCMethodDecl -/// ObjCContainerDecl -/// LinkageSpecDecl -/// BlockDecl -/// -class DeclContext { - /// DeclKind - This indicates which class this is. - 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; - - /// \brief Whether this declaration context also has some external - /// storage that contains additional declarations that are visible - /// in this context. - mutable bool ExternalVisibleStorage : 1; - - /// \brief Whether this declaration context has had external visible - /// storage added since the last lookup. In this case, \c LookupPtr's - /// invariant may not hold and needs to be fixed before we perform - /// another lookup. - mutable bool NeedToReconcileExternalVisibleStorage : 1; - - /// \brief If \c true, this context may have local lexical declarations - /// that are missing from the lookup table. - mutable bool HasLazyLocalLexicalLookups : 1; - - /// \brief If \c true, the external source may have lexical declarations - /// that are missing from the lookup table. - mutable bool HasLazyExternalLexicalLookups : 1; - - /// \brief If \c true, lookups should only return identifier from - /// DeclContext scope (for example TranslationUnit). Used in - /// LookupQualifiedName() - mutable bool UseQualifiedLookup : 1; - - /// \brief Pointer to the data structure used to lookup declarations - /// within this context (or a DependentStoredDeclsMap if this is a - /// dependent context). We maintain the invariant that, if the map - /// contains an entry for a DeclarationName (and we haven't lazily - /// omitted anything), then it contains all relevant entries for that - /// name (modulo the hasExternalDecls() flag). - mutable StoredDeclsMap *LookupPtr; - -protected: - /// FirstDecl - The first declaration stored within this declaration - /// context. - mutable Decl *FirstDecl; - - /// LastDecl - The last declaration stored within this declaration - /// context. FIXME: We could probably cache this value somewhere - /// outside of the DeclContext, to reduce the size of DeclContext by - /// another pointer. - mutable Decl *LastDecl; - - friend class ExternalASTSource; - friend class ASTDeclReader; - friend class ASTWriter; - - /// \brief Build up a chain of declarations. - /// - /// \returns the first/last pair of declarations. - static std::pair<Decl *, Decl *> - BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded); - - DeclContext(Decl::Kind K) - : DeclKind(K), ExternalLexicalStorage(false), - ExternalVisibleStorage(false), - NeedToReconcileExternalVisibleStorage(false), - HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false), - UseQualifiedLookup(false), - LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {} - -public: - ~DeclContext(); - - Decl::Kind getDeclKind() const { - return static_cast<Decl::Kind>(DeclKind); - } - const char *getDeclKindName() const; - - /// getParent - Returns the containing DeclContext. - DeclContext *getParent() { - return cast<Decl>(this)->getDeclContext(); - } - const DeclContext *getParent() const { - return const_cast<DeclContext*>(this)->getParent(); - } - - /// getLexicalParent - Returns the containing lexical DeclContext. May be - /// different from getParent, e.g.: - /// - /// namespace A { - /// struct S; - /// } - /// struct A::S {}; // getParent() == namespace 'A' - /// // getLexicalParent() == translation unit - /// - DeclContext *getLexicalParent() { - return cast<Decl>(this)->getLexicalDeclContext(); - } - const DeclContext *getLexicalParent() const { - return const_cast<DeclContext*>(this)->getLexicalParent(); - } - - DeclContext *getLookupParent(); - - const DeclContext *getLookupParent() const { - return const_cast<DeclContext*>(this)->getLookupParent(); - } - - ASTContext &getParentASTContext() const { - return cast<Decl>(this)->getASTContext(); - } - - bool isClosure() const { - return DeclKind == Decl::Block; - } - - bool isObjCContainer() const { - switch (DeclKind) { - case Decl::ObjCCategory: - case Decl::ObjCCategoryImpl: - case Decl::ObjCImplementation: - case Decl::ObjCInterface: - case Decl::ObjCProtocol: - return true; - } - return false; - } - - bool isFunctionOrMethod() const { - switch (DeclKind) { - case Decl::Block: - case Decl::Captured: - case Decl::ObjCMethod: - return true; - default: - return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction; - } - } - - /// \brief Test whether the context supports looking up names. - bool isLookupContext() const { - return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec; - } - - bool isFileContext() const { - return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace; - } - - bool isTranslationUnit() const { - return DeclKind == Decl::TranslationUnit; - } - - bool isRecord() const { - return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord; - } - - bool isNamespace() const { - return DeclKind == Decl::Namespace; - } - - bool isStdNamespace() const; - - bool isInlineNamespace() const; - - /// \brief Determines whether this context is dependent on a - /// template parameter. - bool isDependentContext() const; - - /// isTransparentContext - Determines whether this context is a - /// "transparent" context, meaning that the members declared in this - /// context are semantically declared in the nearest enclosing - /// non-transparent (opaque) context but are lexically declared in - /// this context. For example, consider the enumerators of an - /// enumeration type: - /// @code - /// enum E { - /// Val1 - /// }; - /// @endcode - /// Here, E is a transparent context, so its enumerator (Val1) will - /// appear (semantically) that it is in the same context of E. - /// Examples of transparent contexts include: enumerations (except for - /// C++0x scoped enums), and C++ linkage specifications. - bool isTransparentContext() const; - - /// \brief Determines whether this context or some of its ancestors is a - /// linkage specification context that specifies C linkage. - bool isExternCContext() const; - - /// \brief Determines whether this context or some of its ancestors is a - /// linkage specification context that specifies C++ linkage. - bool isExternCXXContext() const; - - /// \brief Determine whether this declaration context is equivalent - /// to the declaration context DC. - bool Equals(const DeclContext *DC) const { - return DC && this->getPrimaryContext() == DC->getPrimaryContext(); - } - - /// \brief Determine whether this declaration context encloses the - /// declaration context DC. - bool Encloses(const DeclContext *DC) const; - - /// \brief Find the nearest non-closure ancestor of this context, - /// i.e. the innermost semantic parent of this context which is not - /// a closure. A context may be its own non-closure ancestor. - Decl *getNonClosureAncestor(); - const Decl *getNonClosureAncestor() const { - return const_cast<DeclContext*>(this)->getNonClosureAncestor(); - } - - /// getPrimaryContext - There may be many different - /// declarations of the same entity (including forward declarations - /// of classes, multiple definitions of namespaces, etc.), each with - /// a different set of declarations. This routine returns the - /// "primary" DeclContext structure, which will contain the - /// information needed to perform name lookup into this context. - DeclContext *getPrimaryContext(); - const DeclContext *getPrimaryContext() const { - return const_cast<DeclContext*>(this)->getPrimaryContext(); - } - - /// getRedeclContext - Retrieve the context in which an entity conflicts with - /// other entities of the same name, or where it is a redeclaration if the - /// two entities are compatible. This skips through transparent contexts. - DeclContext *getRedeclContext(); - const DeclContext *getRedeclContext() const { - return const_cast<DeclContext *>(this)->getRedeclContext(); - } - - /// \brief Retrieve the nearest enclosing namespace context. - DeclContext *getEnclosingNamespaceContext(); - const DeclContext *getEnclosingNamespaceContext() const { - return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); - } - - /// \brief Retrieve the outermost lexically enclosing record context. - RecordDecl *getOuterLexicalRecordContext(); - const RecordDecl *getOuterLexicalRecordContext() const { - return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext(); - } - - /// \brief Test if this context is part of the enclosing namespace set of - /// the context NS, as defined in C++0x [namespace.def]p9. If either context - /// isn't a namespace, this is equivalent to Equals(). - /// - /// The enclosing namespace set of a namespace is the namespace and, if it is - /// inline, its enclosing namespace, recursively. - bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; - - /// \brief Collects all of the declaration contexts that are semantically - /// connected to this declaration context. - /// - /// For declaration contexts that have multiple semantically connected but - /// syntactically distinct contexts, such as C++ namespaces, this routine - /// retrieves the complete set of such declaration contexts in source order. - /// For example, given: - /// - /// \code - /// namespace N { - /// int x; - /// } - /// namespace N { - /// int y; - /// } - /// \endcode - /// - /// The \c Contexts parameter will contain both definitions of N. - /// - /// \param Contexts Will be cleared and set to the set of declaration - /// contexts that are semanticaly connected to this declaration context, - /// in source order, including this context (which may be the only result, - /// for non-namespace contexts). - void collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts); - - /// decl_iterator - Iterates through the declarations stored - /// within this context. - class decl_iterator { - /// Current - The current declaration. - Decl *Current; - - public: - typedef Decl *value_type; - typedef const value_type &reference; - typedef const value_type *pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - decl_iterator() : Current(nullptr) { } - explicit decl_iterator(Decl *C) : Current(C) { } - - reference operator*() const { return Current; } - // This doesn't meet the iterator requirements, but it's convenient - value_type operator->() const { return Current; } - - decl_iterator& operator++() { - Current = Current->getNextDeclInContext(); - return *this; - } - - decl_iterator operator++(int) { - decl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(decl_iterator x, decl_iterator y) { - return x.Current == y.Current; - } - friend bool operator!=(decl_iterator x, decl_iterator y) { - return x.Current != y.Current; - } - }; - - typedef llvm::iterator_range<decl_iterator> decl_range; - - /// decls_begin/decls_end - Iterate over the declarations stored in - /// this context. - decl_range decls() const { return decl_range(decls_begin(), decls_end()); } - decl_iterator decls_begin() const; - decl_iterator decls_end() const { return decl_iterator(); } - bool decls_empty() const; - - /// noload_decls_begin/end - Iterate over the declarations stored in this - /// context that are currently loaded; don't attempt to retrieve anything - /// from an external source. - decl_range noload_decls() const { - return decl_range(noload_decls_begin(), noload_decls_end()); - } - decl_iterator noload_decls_begin() const { return decl_iterator(FirstDecl); } - decl_iterator noload_decls_end() const { return decl_iterator(); } - - /// specific_decl_iterator - Iterates over a subrange of - /// declarations stored in a DeclContext, providing only those that - /// are of type SpecificDecl (or a class derived from it). This - /// iterator is used, for example, to provide iteration over just - /// the fields within a RecordDecl (with SpecificDecl = FieldDecl). - template<typename SpecificDecl> - class specific_decl_iterator { - /// Current - The current, underlying declaration iterator, which - /// will either be NULL or will point to a declaration of - /// type SpecificDecl. - DeclContext::decl_iterator Current; - - /// SkipToNextDecl - Advances the current position up to the next - /// declaration of type SpecificDecl that also meets the criteria - /// required by Acceptable. - void SkipToNextDecl() { - while (*Current && !isa<SpecificDecl>(*Current)) - ++Current; - } - - public: - typedef SpecificDecl *value_type; - // TODO: Add reference and pointer typedefs (with some appropriate proxy - // type) if we ever have a need for them. - typedef void reference; - typedef void pointer; - typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type - difference_type; - typedef std::forward_iterator_tag iterator_category; - - specific_decl_iterator() : Current() { } - - /// specific_decl_iterator - Construct a new iterator over a - /// subset of the declarations the range [C, - /// end-of-declarations). If A is non-NULL, it is a pointer to a - /// member function of SpecificDecl that should return true for - /// all of the SpecificDecl instances that will be in the subset - /// of iterators. For example, if you want Objective-C instance - /// methods, SpecificDecl will be ObjCMethodDecl and A will be - /// &ObjCMethodDecl::isInstanceMethod. - explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) { - SkipToNextDecl(); - } - - value_type operator*() const { return cast<SpecificDecl>(*Current); } - // This doesn't meet the iterator requirements, but it's convenient - value_type operator->() const { return **this; } - - specific_decl_iterator& operator++() { - ++Current; - SkipToNextDecl(); - return *this; - } - - specific_decl_iterator operator++(int) { - specific_decl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(const specific_decl_iterator& x, - const specific_decl_iterator& y) { - return x.Current == y.Current; - } - - friend bool operator!=(const specific_decl_iterator& x, - const specific_decl_iterator& y) { - return x.Current != y.Current; - } - }; - - /// \brief Iterates over a filtered subrange of declarations stored - /// in a DeclContext. - /// - /// This iterator visits only those declarations that are of type - /// SpecificDecl (or a class derived from it) and that meet some - /// additional run-time criteria. This iterator is used, for - /// example, to provide access to the instance methods within an - /// Objective-C interface (with SpecificDecl = ObjCMethodDecl and - /// Acceptable = ObjCMethodDecl::isInstanceMethod). - template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const> - class filtered_decl_iterator { - /// Current - The current, underlying declaration iterator, which - /// will either be NULL or will point to a declaration of - /// type SpecificDecl. - DeclContext::decl_iterator Current; - - /// SkipToNextDecl - Advances the current position up to the next - /// declaration of type SpecificDecl that also meets the criteria - /// required by Acceptable. - void SkipToNextDecl() { - while (*Current && - (!isa<SpecificDecl>(*Current) || - (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)()))) - ++Current; - } - - public: - typedef SpecificDecl *value_type; - // TODO: Add reference and pointer typedefs (with some appropriate proxy - // type) if we ever have a need for them. - typedef void reference; - typedef void pointer; - typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type - difference_type; - typedef std::forward_iterator_tag iterator_category; - - filtered_decl_iterator() : Current() { } - - /// filtered_decl_iterator - Construct a new iterator over a - /// subset of the declarations the range [C, - /// end-of-declarations). If A is non-NULL, it is a pointer to a - /// member function of SpecificDecl that should return true for - /// all of the SpecificDecl instances that will be in the subset - /// of iterators. For example, if you want Objective-C instance - /// methods, SpecificDecl will be ObjCMethodDecl and A will be - /// &ObjCMethodDecl::isInstanceMethod. - explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) { - SkipToNextDecl(); - } - - value_type operator*() const { return cast<SpecificDecl>(*Current); } - value_type operator->() const { return cast<SpecificDecl>(*Current); } - - filtered_decl_iterator& operator++() { - ++Current; - SkipToNextDecl(); - return *this; - } - - filtered_decl_iterator operator++(int) { - filtered_decl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(const filtered_decl_iterator& x, - const filtered_decl_iterator& y) { - return x.Current == y.Current; - } - - friend bool operator!=(const filtered_decl_iterator& x, - const filtered_decl_iterator& y) { - return x.Current != y.Current; - } - }; - - /// @brief Add the declaration D into this context. - /// - /// This routine should be invoked when the declaration D has first - /// been declared, to place D into the context where it was - /// (lexically) defined. Every declaration must be added to one - /// (and only one!) context, where it can be visited via - /// [decls_begin(), decls_end()). Once a declaration has been added - /// to its lexical context, the corresponding DeclContext owns the - /// declaration. - /// - /// If D is also a NamedDecl, it will be made visible within its - /// semantic context via makeDeclVisibleInContext. - void addDecl(Decl *D); - - /// @brief Add the declaration D into this context, but suppress - /// searches for external declarations with the same name. - /// - /// Although analogous in function to addDecl, this removes an - /// important check. This is only useful if the Decl is being - /// added in response to an external search; in all other cases, - /// addDecl() is the right function to use. - /// See the ASTImporter for use cases. - void addDeclInternal(Decl *D); - - /// @brief Add the declaration D to this context without modifying - /// any lookup tables. - /// - /// This is useful for some operations in dependent contexts where - /// the semantic context might not be dependent; this basically - /// only happens with friends. - void addHiddenDecl(Decl *D); - - /// @brief Removes a declaration from this context. - void removeDecl(Decl *D); - - /// @brief Checks whether a declaration is in this context. - bool containsDecl(Decl *D) const; - - typedef DeclContextLookupResult lookup_result; - typedef lookup_result::iterator lookup_iterator; - - /// lookup - Find the declarations (if any) with the given Name in - /// this context. Returns a range of iterators that contains all of - /// the declarations with this name, with object, function, member, - /// and enumerator names preceding any tag name. Note that this - /// routine will not look into parent contexts. - lookup_result lookup(DeclarationName Name) const; - - /// \brief Find the declarations with the given name that are visible - /// within this context; don't attempt to retrieve anything from an - /// external source. - lookup_result noload_lookup(DeclarationName Name); - - /// \brief A simplistic name lookup mechanism that performs name lookup - /// into this declaration context without consulting the external source. - /// - /// This function should almost never be used, because it subverts the - /// usual relationship between a DeclContext and the external source. - /// See the ASTImporter for the (few, but important) use cases. - /// - /// FIXME: This is very inefficient; replace uses of it with uses of - /// noload_lookup. - void localUncachedLookup(DeclarationName Name, - SmallVectorImpl<NamedDecl *> &Results); - - /// @brief Makes a declaration visible within this context. - /// - /// This routine makes the declaration D visible to name lookup - /// within this context and, if this is a transparent context, - /// within its parent contexts up to the first enclosing - /// non-transparent context. Making a declaration visible within a - /// context does not transfer ownership of a declaration, and a - /// declaration can be visible in many contexts that aren't its - /// lexical context. - /// - /// If D is a redeclaration of an existing declaration that is - /// visible from this context, as determined by - /// NamedDecl::declarationReplaces, the previous declaration will be - /// replaced with D. - void makeDeclVisibleInContext(NamedDecl *D); - - /// all_lookups_iterator - An iterator that provides a view over the results - /// of looking up every possible name. - class all_lookups_iterator; - - typedef llvm::iterator_range<all_lookups_iterator> lookups_range; - - lookups_range lookups() const; - lookups_range noload_lookups() const; - - /// \brief Iterators over all possible lookups within this context. - all_lookups_iterator lookups_begin() const; - all_lookups_iterator lookups_end() const; - - /// \brief Iterators over all possible lookups within this context that are - /// currently loaded; don't attempt to retrieve anything from an external - /// source. - all_lookups_iterator noload_lookups_begin() const; - all_lookups_iterator noload_lookups_end() const; - - struct udir_iterator; - typedef llvm::iterator_adaptor_base<udir_iterator, lookup_iterator, - std::random_access_iterator_tag, - UsingDirectiveDecl *> udir_iterator_base; - struct udir_iterator : udir_iterator_base { - udir_iterator(lookup_iterator I) : udir_iterator_base(I) {} - UsingDirectiveDecl *operator*() const; - }; - - typedef llvm::iterator_range<udir_iterator> udir_range; - - udir_range using_directives() const; - - // These are all defined in DependentDiagnostic.h. - class ddiag_iterator; - typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range; - - inline ddiag_range ddiags() const; - - // Low-level accessors - - /// \brief Mark that there are external lexical declarations that we need - /// to include in our lookup table (and that are not available as external - /// visible lookups). These extra lookup results will be found by walking - /// the lexical declarations of this context. This should be used only if - /// setHasExternalLexicalStorage() has been called on any decl context for - /// which this is the primary context. - void setMustBuildLookupTable() { - assert(this == getPrimaryContext() && - "should only be called on primary context"); - HasLazyExternalLexicalLookups = true; - } - - /// \brief Retrieve the internal representation of the lookup structure. - /// This may omit some names if we are lazily building the structure. - StoredDeclsMap *getLookupPtr() const { return LookupPtr; } - - /// \brief Ensure the lookup structure is fully-built and return it. - StoredDeclsMap *buildLookup(); - - /// \brief Whether this DeclContext has external storage containing - /// additional declarations that are lexically in this context. - bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; } - - /// \brief State whether this DeclContext has external storage for - /// declarations lexically in this context. - void setHasExternalLexicalStorage(bool ES = true) { - ExternalLexicalStorage = ES; - } - - /// \brief Whether this DeclContext has external storage containing - /// additional declarations that are visible in this context. - bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; } - - /// \brief State whether this DeclContext has external storage for - /// declarations visible in this context. - void setHasExternalVisibleStorage(bool ES = true) { - ExternalVisibleStorage = ES; - if (ES && LookupPtr) - NeedToReconcileExternalVisibleStorage = true; - } - - /// \brief Determine whether the given declaration is stored in the list of - /// declarations lexically within this context. - bool isDeclInLexicalTraversal(const Decl *D) const { - return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl || - D == LastDecl); - } - - bool setUseQualifiedLookup(bool use = true) { - bool old_value = UseQualifiedLookup; - UseQualifiedLookup = use; - return old_value; - } - - bool shouldUseQualifiedLookup() const { - return UseQualifiedLookup; - } - - static bool classof(const Decl *D); - static bool classof(const DeclContext *D) { return true; } - - void dumpDeclContext() const; - void dumpLookups() const; - void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const; - -private: - void reconcileExternalVisibleStorage() const; - bool LoadLexicalDeclsFromExternalStorage() const; - - /// @brief Makes a declaration visible within this context, but - /// suppresses searches for external declarations with the same - /// name. - /// - /// Analogous to makeDeclVisibleInContext, but for the exclusive - /// use of addDeclInternal(). - void makeDeclVisibleInContextInternal(NamedDecl *D); - - friend class DependentDiagnostic; - StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; - - void buildLookupImpl(DeclContext *DCtx, bool Internal); - void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, - bool Rediscoverable); - void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal); -}; - -inline bool Decl::isTemplateParameter() const { - return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm || - getKind() == TemplateTemplateParm; -} - -// Specialization selected when ToTy is not a known subclass of DeclContext. -template <class ToTy, - bool IsKnownSubtype = ::std::is_base_of<DeclContext, ToTy>::value> -struct cast_convert_decl_context { - static const ToTy *doit(const DeclContext *Val) { - return static_cast<const ToTy*>(Decl::castFromDeclContext(Val)); - } - - static ToTy *doit(DeclContext *Val) { - return static_cast<ToTy*>(Decl::castFromDeclContext(Val)); - } -}; - -// Specialization selected when ToTy is a known subclass of DeclContext. -template <class ToTy> -struct cast_convert_decl_context<ToTy, true> { - static const ToTy *doit(const DeclContext *Val) { - return static_cast<const ToTy*>(Val); - } - - static ToTy *doit(DeclContext *Val) { - return static_cast<ToTy*>(Val); - } -}; - - -} // end clang. - -namespace llvm { - -/// isa<T>(DeclContext*) -template <typename To> -struct isa_impl<To, ::clang::DeclContext> { - static bool doit(const ::clang::DeclContext &Val) { - return To::classofKind(Val.getDeclKind()); - } -}; - -/// cast<T>(DeclContext*) -template<class ToTy> -struct cast_convert_val<ToTy, - const ::clang::DeclContext,const ::clang::DeclContext> { - static const ToTy &doit(const ::clang::DeclContext &Val) { - return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); - } -}; -template<class ToTy> -struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> { - static ToTy &doit(::clang::DeclContext &Val) { - return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); - } -}; -template<class ToTy> -struct cast_convert_val<ToTy, - const ::clang::DeclContext*, const ::clang::DeclContext*> { - static const ToTy *doit(const ::clang::DeclContext *Val) { - return ::clang::cast_convert_decl_context<ToTy>::doit(Val); - } -}; -template<class ToTy> -struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> { - static ToTy *doit(::clang::DeclContext *Val) { - return ::clang::cast_convert_decl_context<ToTy>::doit(Val); - } -}; - -/// Implement cast_convert_val for Decl -> DeclContext conversions. -template<class FromTy> -struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> { - static ::clang::DeclContext &doit(const FromTy &Val) { - return *FromTy::castToDeclContext(&Val); - } -}; - -template<class FromTy> -struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> { - static ::clang::DeclContext *doit(const FromTy *Val) { - return FromTy::castToDeclContext(Val); - } -}; - -template<class FromTy> -struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> { - static const ::clang::DeclContext &doit(const FromTy &Val) { - return *FromTy::castToDeclContext(&Val); - } -}; - -template<class FromTy> -struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> { - static const ::clang::DeclContext *doit(const FromTy *Val) { - return FromTy::castToDeclContext(Val); - } -}; - -} // end namespace llvm - -#endif diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h deleted file mode 100644 index 7c54901..0000000 --- a/include/clang/AST/DeclCXX.h +++ /dev/null @@ -1,3249 +0,0 @@ -//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the C++ Decl subclasses, other than those for templates -/// (found in DeclTemplate.h) and friends (in DeclFriend.h). -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLCXX_H -#define LLVM_CLANG_AST_DECLCXX_H - -#include "clang/AST/ASTUnresolvedSet.h" -#include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/LambdaCapture.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -class ClassTemplateDecl; -class ClassTemplateSpecializationDecl; -class CXXBasePath; -class CXXBasePaths; -class CXXConstructorDecl; -class CXXConversionDecl; -class CXXDestructorDecl; -class CXXMethodDecl; -class CXXRecordDecl; -class CXXMemberLookupCriteria; -class CXXFinalOverriderMap; -class CXXIndirectPrimaryBaseSet; -class FriendDecl; -class LambdaExpr; -class UsingDecl; - -/// \brief Represents any kind of function declaration, whether it is a -/// concrete function or a function template. -class AnyFunctionDecl { - NamedDecl *Function; - - AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } - -public: - AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } - AnyFunctionDecl(FunctionTemplateDecl *FTD); - - /// \brief Implicily converts any function or function template into a - /// named declaration. - operator NamedDecl *() const { return Function; } - - /// \brief Retrieve the underlying function or function template. - NamedDecl *get() const { return Function; } - - static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { - return AnyFunctionDecl(ND); - } -}; - -} // end namespace clang - -namespace llvm { - // Provide PointerLikeTypeTraits for non-cvr pointers. - template<> - class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { - public: - static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) { - return F.get(); - } - static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { - return ::clang::AnyFunctionDecl::getFromNamedDecl( - static_cast< ::clang::NamedDecl*>(P)); - } - - enum { NumLowBitsAvailable = 2 }; - }; - -} // end namespace llvm - -namespace clang { - -/// \brief Represents an access specifier followed by colon ':'. -/// -/// An objects of this class represents sugar for the syntactic occurrence -/// of an access specifier followed by a colon in the list of member -/// specifiers of a C++ class definition. -/// -/// Note that they do not represent other uses of access specifiers, -/// such as those occurring in a list of base specifiers. -/// Also note that this class has nothing to do with so-called -/// "access declarations" (C++98 11.3 [class.access.dcl]). -class AccessSpecDecl : public Decl { - virtual void anchor(); - /// \brief The location of the ':'. - SourceLocation ColonLoc; - - AccessSpecDecl(AccessSpecifier AS, DeclContext *DC, - SourceLocation ASLoc, SourceLocation ColonLoc) - : Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) { - setAccess(AS); - } - AccessSpecDecl(EmptyShell Empty) - : Decl(AccessSpec, Empty) { } -public: - /// \brief The location of the access specifier. - SourceLocation getAccessSpecifierLoc() const { return getLocation(); } - /// \brief Sets the location of the access specifier. - void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); } - - /// \brief The location of the colon following the access specifier. - SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Sets the location of the colon. - void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(getAccessSpecifierLoc(), getColonLoc()); - } - - static AccessSpecDecl *Create(ASTContext &C, AccessSpecifier AS, - DeclContext *DC, SourceLocation ASLoc, - SourceLocation ColonLoc) { - return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); - } - static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == AccessSpec; } -}; - - -/// \brief Represents a base class of a C++ class. -/// -/// Each CXXBaseSpecifier represents a single, direct base class (or -/// struct) of a C++ class (or struct). It specifies the type of that -/// base class, whether it is a virtual or non-virtual base, and what -/// level of access (public, protected, private) is used for the -/// derivation. For example: -/// -/// \code -/// class A { }; -/// class B { }; -/// class C : public virtual A, protected B { }; -/// \endcode -/// -/// In this code, C will have two CXXBaseSpecifiers, one for "public -/// virtual A" and the other for "protected B". -class CXXBaseSpecifier { - /// \brief The source code range that covers the full base - /// specifier, including the "virtual" (if present) and access - /// specifier (if present). - SourceRange Range; - - /// \brief The source location of the ellipsis, if this is a pack - /// expansion. - SourceLocation EllipsisLoc; - - /// \brief Whether this is a virtual base class or not. - bool Virtual : 1; - - /// \brief Whether this is the base of a class (true) or of a struct (false). - /// - /// This determines the mapping from the access specifier as written in the - /// source code to the access specifier used for semantic analysis. - bool BaseOfClass : 1; - - /// \brief Access specifier as written in the source code (may be AS_none). - /// - /// The actual type of data stored here is an AccessSpecifier, but we use - /// "unsigned" here to work around a VC++ bug. - unsigned Access : 2; - - /// \brief Whether the class contains a using declaration - /// to inherit the named class's constructors. - bool InheritConstructors : 1; - - /// \brief 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 \c virtual or the access specifier. - TypeSourceInfo *BaseTypeInfo; - -public: - CXXBaseSpecifier() { } - - CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, - TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) - : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), - Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { } - - /// \brief Retrieves the source range that contains the entire base specifier. - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - - /// \brief Determines whether the base class is a virtual base class (or not). - bool isVirtual() const { return Virtual; } - - /// \brief Determine whether this base class is a base of a class declared - /// 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; - } - - /// \brief 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 retrieve the access specifier as - /// written in the source code, use getAccessSpecifierAsWritten(). - AccessSpecifier getAccessSpecifier() const { - if ((AccessSpecifier)Access == AS_none) - return BaseOfClass? AS_private : AS_public; - else - return (AccessSpecifier)Access; - } - - /// \brief Retrieves the access specifier as written in the source code - /// (which may mean that no access specifier was explicitly written). - /// - /// Use getAccessSpecifier() to retrieve the access specifier for use in - /// semantic analysis. - AccessSpecifier getAccessSpecifierAsWritten() const { - return (AccessSpecifier)Access; - } - - /// \brief Retrieves the type of the base class. - /// - /// This type will always be an unqualified class type. - QualType getType() const { - return BaseTypeInfo->getType().getUnqualifiedType(); - } - - /// \brief Retrieves the type and source location of the base class. - TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } -}; - -/// \brief A lazy pointer to the definition data for a declaration. -/// FIXME: This is a little CXXRecordDecl-specific that the moment. -template<typename Decl, typename T> class LazyDefinitionDataPtr { - llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl; - - LazyDefinitionDataPtr update() { - if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) { - if (Canon->isCanonicalDecl()) - Canon->getMostRecentDecl(); - else - // Declaration isn't canonical any more; - // update it and perform path compression. - *this = Canon->getPreviousDecl()->DefinitionData.update(); - } - return *this; - } - -public: - LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {} - LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {} - T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); } - T *get() { return update().getNotUpdated(); } -}; - -/// \brief Represents a C++ struct/union/class. -class CXXRecordDecl : public RecordDecl { - - friend void TagDecl::startDefinition(); - - /// Values used in DefinitionData fields to represent special members. - enum SpecialMemberFlags { - SMF_DefaultConstructor = 0x1, - SMF_CopyConstructor = 0x2, - SMF_MoveConstructor = 0x4, - SMF_CopyAssignment = 0x8, - SMF_MoveAssignment = 0x10, - SMF_Destructor = 0x20, - SMF_All = 0x3f - }; - - struct DefinitionData { - DefinitionData(CXXRecordDecl *D); - - /// \brief True if this class has any user-declared constructors. - bool UserDeclaredConstructor : 1; - - /// \brief The user-declared special members which this class has. - unsigned UserDeclaredSpecialMembers : 6; - - /// \brief True when this class is an aggregate. - bool Aggregate : 1; - - /// \brief True when this class is a POD-type. - bool PlainOldData : 1; - - /// true when this class is empty for traits purposes, - /// i.e. has no data members other than 0-width bit-fields, has no - /// virtual function/base, and doesn't inherit from a non-empty - /// class. Doesn't take union-ness into account. - bool Empty : 1; - - /// \brief True when this class is polymorphic, i.e., has at - /// least one virtual member or derives from a polymorphic class. - bool Polymorphic : 1; - - /// \brief True when this class is abstract, i.e., has at least - /// one pure virtual function, (that can come from a base class). - bool Abstract : 1; - - /// \brief True when this class has standard layout. - /// - /// C++11 [class]p7. A standard-layout class is a class that: - /// * has no non-static data members of type non-standard-layout class (or - /// array of such types) or reference, - /// * has no virtual functions (10.3) and no virtual base classes (10.1), - /// * has the same access control (Clause 11) for all non-static data - /// members - /// * has no non-standard-layout base classes, - /// * either has no non-static data members in the most derived class and at - /// most one base class with non-static data members, or has no base - /// classes with non-static data members, and - /// * has no base classes of the same type as the first non-static data - /// member. - bool IsStandardLayout : 1; - - /// \brief True when there are no non-empty base classes. - /// - /// This is a helper bit of state used to implement IsStandardLayout more - /// efficiently. - bool HasNoNonEmptyBases : 1; - - /// \brief True when there are private non-static data members. - bool HasPrivateFields : 1; - - /// \brief True when there are protected non-static data members. - bool HasProtectedFields : 1; - - /// \brief True when there are private non-static data members. - bool HasPublicFields : 1; - - /// \brief True if this class (or any subobject) has mutable fields. - bool HasMutableFields : 1; - - /// \brief True if this class (or any nested anonymous struct or union) - /// has variant members. - bool HasVariantMembers : 1; - - /// \brief True if there no non-field members declared by the user. - bool HasOnlyCMembers : 1; - - /// \brief True if any field has an in-class initializer, including those - /// within anonymous unions or structs. - bool HasInClassInitializer : 1; - - /// \brief True if any field is of reference type, and does not have an - /// in-class initializer. - /// - /// In this case, value-initialization of this class is illegal in C++98 - /// even if the class has a trivial default constructor. - bool HasUninitializedReferenceMember : 1; - - /// \brief These flags are \c true if a defaulted corresponding special - /// member can't be fully analyzed without performing overload resolution. - /// @{ - bool NeedOverloadResolutionForMoveConstructor : 1; - bool NeedOverloadResolutionForMoveAssignment : 1; - bool NeedOverloadResolutionForDestructor : 1; - /// @} - - /// \brief These flags are \c true if an implicit defaulted corresponding - /// special member would be defined as deleted. - /// @{ - bool DefaultedMoveConstructorIsDeleted : 1; - bool DefaultedMoveAssignmentIsDeleted : 1; - bool DefaultedDestructorIsDeleted : 1; - /// @} - - /// \brief The trivial special members which this class has, per - /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25, - /// C++11 [class.dtor]p5, or would have if the member were not suppressed. - /// - /// This excludes any user-declared but not user-provided special members - /// which have been declared but not yet defined. - unsigned HasTrivialSpecialMembers : 6; - - /// \brief The declared special members of this class which are known to be - /// non-trivial. - /// - /// This excludes any user-declared but not user-provided special members - /// which have been declared but not yet defined, and any implicit special - /// members which have not yet been declared. - unsigned DeclaredNonTrivialSpecialMembers : 6; - - /// \brief True when this class has a destructor with no semantic effect. - bool HasIrrelevantDestructor : 1; - - /// \brief True when this class has at least one user-declared constexpr - /// constructor which is neither the copy nor move constructor. - bool HasConstexprNonCopyMoveConstructor : 1; - - /// \brief True if a defaulted default constructor for this class would - /// be constexpr. - bool DefaultedDefaultConstructorIsConstexpr : 1; - - /// \brief True if this class has a constexpr default constructor. - /// - /// This is true for either a user-declared constexpr default constructor - /// or an implicitly declared constexpr default constructor. - bool HasConstexprDefaultConstructor : 1; - - /// \brief True when this class contains at least one non-static data - /// member or base class of non-literal or volatile type. - bool HasNonLiteralTypeFieldsOrBases : 1; - - /// \brief True when visible conversion functions are already computed - /// and are available. - bool ComputedVisibleConversions : 1; - - /// \brief Whether we have a C++11 user-provided default constructor (not - /// explicitly deleted or defaulted). - bool UserProvidedDefaultConstructor : 1; - - /// \brief The special members which have been declared for this class, - /// either by the user or implicitly. - unsigned DeclaredSpecialMembers : 6; - - /// \brief Whether an implicit copy constructor would have a const-qualified - /// parameter. - bool ImplicitCopyConstructorHasConstParam : 1; - - /// \brief Whether an implicit copy assignment operator would have a - /// const-qualified parameter. - bool ImplicitCopyAssignmentHasConstParam : 1; - - /// \brief Whether any declared copy constructor has a const-qualified - /// parameter. - bool HasDeclaredCopyConstructorWithConstParam : 1; - - /// \brief Whether any declared copy assignment operator has either a - /// const-qualified reference parameter or a non-reference parameter. - bool HasDeclaredCopyAssignmentWithConstParam : 1; - - /// \brief Whether this class describes a C++ lambda. - bool IsLambda : 1; - - /// \brief Whether we are currently parsing base specifiers. - bool IsParsingBaseSpecifiers : 1; - - /// \brief The number of base class specifiers in Bases. - unsigned NumBases; - - /// \brief The number of virtual base class specifiers in VBases. - unsigned NumVBases; - - /// \brief Base classes of this class. - /// - /// FIXME: This is wasted space for a union. - LazyCXXBaseSpecifiersPtr Bases; - - /// \brief direct and indirect virtual base classes of this class. - LazyCXXBaseSpecifiersPtr VBases; - - /// \brief The conversion functions of this C++ class (but not its - /// inherited conversion functions). - /// - /// Each of the entries in this overload set is a CXXConversionDecl. - LazyASTUnresolvedSet Conversions; - - /// \brief The conversion functions of this C++ class and all those - /// inherited conversion functions that are visible in this class. - /// - /// Each of the entries in this overload set is a CXXConversionDecl or a - /// FunctionTemplateDecl. - LazyASTUnresolvedSet VisibleConversions; - - /// \brief The declaration which defines this record. - CXXRecordDecl *Definition; - - /// \brief The first friend declaration in this class, or null if there - /// aren't any. - /// - /// This is actually currently stored in reverse order. - LazyDeclPtr FirstFriend; - - /// \brief Retrieve the set of direct base classes. - CXXBaseSpecifier *getBases() const { - if (!Bases.isOffset()) - return Bases.get(nullptr); - return getBasesSlowCase(); - } - - /// \brief Retrieve the set of virtual base classes. - CXXBaseSpecifier *getVBases() const { - if (!VBases.isOffset()) - return VBases.get(nullptr); - return getVBasesSlowCase(); - } - - private: - CXXBaseSpecifier *getBasesSlowCase() const; - CXXBaseSpecifier *getVBasesSlowCase() const; - }; - - typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData> - DefinitionDataPtr; - friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>; - - mutable DefinitionDataPtr DefinitionData; - - /// \brief Describes a C++ closure type (generated by a lambda expression). - struct LambdaDefinitionData : public DefinitionData { - typedef LambdaCapture Capture; - - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), - CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), - ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr), - MethodTyInfo(Info) { - IsLambda = true; - - // C++11 [expr.prim.lambda]p3: - // This class type is neither an aggregate nor a literal type. - Aggregate = false; - PlainOldData = false; - HasNonLiteralTypeFieldsOrBases = true; - } - - /// \brief Whether this lambda is known to be dependent, even if its - /// context isn't dependent. - /// - /// A lambda with a non-dependent context can be dependent if it occurs - /// within the default argument of a function template, because the - /// lambda will have been created with the enclosing context as its - /// declaration context, rather than function. This is an unfortunate - /// artifact of having to parse the default arguments before. - unsigned Dependent : 1; - - /// \brief Whether this lambda is a generic lambda. - unsigned IsGenericLambda : 1; - - /// \brief The Default Capture. - unsigned CaptureDefault : 2; - - /// \brief The number of captures in this lambda is limited 2^NumCaptures. - unsigned NumCaptures : 15; - - /// \brief The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 13; - - /// \brief The number used to indicate this lambda expression for name - /// mangling in the Itanium C++ ABI. - unsigned ManglingNumber; - - /// \brief The declaration that provides context for this lambda, if the - /// actual DeclContext does not suffice. This is used for lambdas that - /// occur within default arguments of function parameters within the class - /// or within a data member initializer. - Decl *ContextDecl; - - /// \brief The list of captures, both explicit and implicit, for this - /// lambda. - Capture *Captures; - - /// \brief The type of the call method. - TypeSourceInfo *MethodTyInfo; - - }; - - struct DefinitionData &data() const { - auto *DD = DefinitionData.get(); - assert(DD && "queried property of class with no definition"); - return *DD; - } - - struct LambdaDefinitionData &getLambdaData() const { - // No update required: a merged definition cannot change any lambda - // properties. - auto *DD = DefinitionData.getNotUpdated(); - assert(DD && DD->IsLambda && "queried lambda property of non-lambda class"); - return static_cast<LambdaDefinitionData&>(*DD); - } - - /// \brief The template or declaration that this declaration - /// describes or was instantiated from, respectively. - /// - /// For non-templates, this value will be null. For record - /// declarations that describe a class template, this will be a - /// pointer to a ClassTemplateDecl. For member - /// classes of class template specializations, this will be the - /// MemberSpecializationInfo referring to the member class that was - /// instantiated or specialized. - llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> - TemplateOrInstantiation; - - friend class DeclContext; - friend class LambdaExpr; - - /// \brief Called from setBases and addedMember to notify the class that a - /// direct or virtual base class or a member of class type has been added. - void addedClassSubobject(CXXRecordDecl *Base); - - /// \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); - - friend class ASTNodeImporter; - - /// \brief Get the head of our list of friend declarations, possibly - /// deserializing the friends from an external AST source. - FriendDecl *getFirstFriend() const; - -protected: - CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, CXXRecordDecl *PrevDecl); - -public: - /// \brief Iterator that traverses the base classes of a class. - typedef CXXBaseSpecifier* base_class_iterator; - - /// \brief Iterator that traverses the base classes of a class. - typedef const CXXBaseSpecifier* base_class_const_iterator; - - CXXRecordDecl *getCanonicalDecl() override { - return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); - } - const CXXRecordDecl *getCanonicalDecl() const { - return const_cast<CXXRecordDecl*>(this)->getCanonicalDecl(); - } - - CXXRecordDecl *getPreviousDecl() { - return cast_or_null<CXXRecordDecl>( - static_cast<RecordDecl *>(this)->getPreviousDecl()); - } - const CXXRecordDecl *getPreviousDecl() const { - return const_cast<CXXRecordDecl*>(this)->getPreviousDecl(); - } - - CXXRecordDecl *getMostRecentDecl() { - return cast<CXXRecordDecl>( - static_cast<RecordDecl *>(this)->getMostRecentDecl()); - } - - const CXXRecordDecl *getMostRecentDecl() const { - return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl(); - } - - CXXRecordDecl *getDefinition() const { - auto *DD = DefinitionData.get(); - return DD ? DD->Definition : nullptr; - } - - bool hasDefinition() const { return DefinitionData.get(); } - - static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, - CXXRecordDecl *PrevDecl = nullptr, - bool DelayTypeCreation = false); - static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, - TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda, bool IsGeneric, - LambdaCaptureDefault CaptureDefault); - static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - - bool isDynamicClass() const { - return data().Polymorphic || data().NumVBases != 0; - } - - void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; } - - bool isParsingBaseSpecifiers() const { - return data().IsParsingBaseSpecifiers; - } - - /// \brief Sets the base classes of this struct or class. - void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); - - /// \brief Retrieves the number of base classes of this class. - unsigned getNumBases() const { return data().NumBases; } - - typedef llvm::iterator_range<base_class_iterator> base_class_range; - typedef llvm::iterator_range<base_class_const_iterator> - base_class_const_range; - - base_class_range bases() { - return base_class_range(bases_begin(), bases_end()); - } - base_class_const_range bases() const { - return base_class_const_range(bases_begin(), bases_end()); - } - - 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; - } - - /// \brief Retrieves the number of virtual base classes of this class. - unsigned getNumVBases() const { return data().NumVBases; } - - base_class_range vbases() { - return base_class_range(vbases_begin(), vbases_end()); - } - base_class_const_range vbases() const { - return base_class_const_range(vbases_begin(), vbases_end()); - } - - 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; - } - - /// \brief Determine whether this class has any dependent base classes which - /// are not the current instantiation. - bool hasAnyDependentBases() const; - - /// Iterator access to method members. The method iterator visits - /// all method members of the class, including non-instance methods, - /// special methods, etc. - typedef specific_decl_iterator<CXXMethodDecl> method_iterator; - typedef llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>> - method_range; - - method_range methods() const { - return method_range(method_begin(), method_end()); - } - - /// \brief Method begin iterator. Iterates in the order the methods - /// were declared. - method_iterator method_begin() const { - return method_iterator(decls_begin()); - } - /// \brief Method past-the-end iterator. - method_iterator method_end() const { - return method_iterator(decls_end()); - } - - /// Iterator access to constructor members. - typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator; - typedef llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>> - ctor_range; - - ctor_range ctors() const { return ctor_range(ctor_begin(), ctor_end()); } - - ctor_iterator ctor_begin() const { - return ctor_iterator(decls_begin()); - } - ctor_iterator ctor_end() const { - return ctor_iterator(decls_end()); - } - - /// An iterator over friend declarations. All of these are defined - /// in DeclFriend.h. - class friend_iterator; - typedef llvm::iterator_range<friend_iterator> friend_range; - - friend_range friends() const; - friend_iterator friend_begin() const; - friend_iterator friend_end() const; - void pushFriendDecl(FriendDecl *FD); - - /// Determines whether this record has any friends. - bool hasFriends() const { - return data().FirstFriend.isValid(); - } - - /// \brief \c true if we know for sure that this class has a single, - /// accessible, unambiguous move constructor that is not deleted. - bool hasSimpleMoveConstructor() const { - return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() && - !data().DefaultedMoveConstructorIsDeleted; - } - /// \brief \c true if we know for sure that this class has a single, - /// accessible, unambiguous move assignment operator that is not deleted. - bool hasSimpleMoveAssignment() const { - return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() && - !data().DefaultedMoveAssignmentIsDeleted; - } - /// \brief \c true if we know for sure that this class has an accessible - /// destructor that is not deleted. - bool hasSimpleDestructor() const { - return !hasUserDeclaredDestructor() && - !data().DefaultedDestructorIsDeleted; - } - - /// \brief Determine whether this class has any default constructors. - bool hasDefaultConstructor() const { - return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) || - needsImplicitDefaultConstructor(); - } - - /// \brief Determine if we need to declare a default constructor for - /// this class. - /// - /// This value is used for lazy creation of default constructors. - bool needsImplicitDefaultConstructor() const { - return !data().UserDeclaredConstructor && - !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) && - // C++14 [expr.prim.lambda]p20: - // The closure type associated with a lambda-expression has no - // default constructor. - !isLambda(); - } - - /// \brief Determine whether this class has any user-declared constructors. - /// - /// When true, a default constructor will not be implicitly declared. - bool hasUserDeclaredConstructor() const { - return data().UserDeclaredConstructor; - } - - /// \brief Whether this class has a user-provided default constructor - /// per C++11. - bool hasUserProvidedDefaultConstructor() const { - return data().UserProvidedDefaultConstructor; - } - - /// \brief Determine whether this class has a user-declared copy constructor. - /// - /// When false, a copy constructor will be implicitly declared. - bool hasUserDeclaredCopyConstructor() const { - return data().UserDeclaredSpecialMembers & SMF_CopyConstructor; - } - - /// \brief Determine whether this class needs an implicit copy - /// constructor to be lazily declared. - bool needsImplicitCopyConstructor() const { - return !(data().DeclaredSpecialMembers & SMF_CopyConstructor); - } - - /// \brief Determine whether we need to eagerly declare a defaulted copy - /// constructor for this class. - bool needsOverloadResolutionForCopyConstructor() const { - return data().HasMutableFields; - } - - /// \brief Determine whether an implicit copy constructor for this type - /// would have a parameter with a const-qualified reference type. - bool implicitCopyConstructorHasConstParam() const { - return data().ImplicitCopyConstructorHasConstParam; - } - - /// \brief Determine whether this class has a copy constructor with - /// a parameter type which is a reference to a const-qualified type. - bool hasCopyConstructorWithConstParam() const { - return data().HasDeclaredCopyConstructorWithConstParam || - (needsImplicitCopyConstructor() && - implicitCopyConstructorHasConstParam()); - } - - /// \brief Whether this class has a user-declared move constructor or - /// assignment operator. - /// - /// When false, a move constructor and assignment operator may be - /// implicitly declared. - bool hasUserDeclaredMoveOperation() const { - return data().UserDeclaredSpecialMembers & - (SMF_MoveConstructor | SMF_MoveAssignment); - } - - /// \brief Determine whether this class has had a move constructor - /// declared by the user. - bool hasUserDeclaredMoveConstructor() const { - return data().UserDeclaredSpecialMembers & SMF_MoveConstructor; - } - - /// \brief Determine whether this class has a move constructor. - bool hasMoveConstructor() const { - return (data().DeclaredSpecialMembers & SMF_MoveConstructor) || - needsImplicitMoveConstructor(); - } - - /// \brief Set that we attempted to declare an implicitly move - /// constructor, but overload resolution failed so we deleted it. - void setImplicitMoveConstructorIsDeleted() { - assert((data().DefaultedMoveConstructorIsDeleted || - needsOverloadResolutionForMoveConstructor()) && - "move constructor should not be deleted"); - data().DefaultedMoveConstructorIsDeleted = true; - } - - /// \brief Determine whether this class should get an implicit move - /// constructor or if any existing special member function inhibits this. - bool needsImplicitMoveConstructor() const { - return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && - !hasUserDeclaredCopyConstructor() && - !hasUserDeclaredCopyAssignment() && - !hasUserDeclaredMoveAssignment() && - !hasUserDeclaredDestructor(); - } - - /// \brief Determine whether we need to eagerly declare a defaulted move - /// constructor for this class. - bool needsOverloadResolutionForMoveConstructor() const { - return data().NeedOverloadResolutionForMoveConstructor; - } - - /// \brief Determine whether this class has a user-declared copy assignment - /// operator. - /// - /// When false, a copy assigment operator will be implicitly declared. - bool hasUserDeclaredCopyAssignment() const { - return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; - } - - /// \brief Determine whether this class needs an implicit copy - /// assignment operator to be lazily declared. - bool needsImplicitCopyAssignment() const { - return !(data().DeclaredSpecialMembers & SMF_CopyAssignment); - } - - /// \brief Determine whether we need to eagerly declare a defaulted copy - /// assignment operator for this class. - bool needsOverloadResolutionForCopyAssignment() const { - return data().HasMutableFields; - } - - /// \brief Determine whether an implicit copy assignment operator for this - /// type would have a parameter with a const-qualified reference type. - bool implicitCopyAssignmentHasConstParam() const { - return data().ImplicitCopyAssignmentHasConstParam; - } - - /// \brief Determine whether this class has a copy assignment operator with - /// a parameter type which is a reference to a const-qualified type or is not - /// a reference. - bool hasCopyAssignmentWithConstParam() const { - return data().HasDeclaredCopyAssignmentWithConstParam || - (needsImplicitCopyAssignment() && - implicitCopyAssignmentHasConstParam()); - } - - /// \brief Determine whether this class has had a move assignment - /// declared by the user. - bool hasUserDeclaredMoveAssignment() const { - return data().UserDeclaredSpecialMembers & SMF_MoveAssignment; - } - - /// \brief Determine whether this class has a move assignment operator. - bool hasMoveAssignment() const { - return (data().DeclaredSpecialMembers & SMF_MoveAssignment) || - needsImplicitMoveAssignment(); - } - - /// \brief Set that we attempted to declare an implicit move assignment - /// operator, but overload resolution failed so we deleted it. - void setImplicitMoveAssignmentIsDeleted() { - assert((data().DefaultedMoveAssignmentIsDeleted || - needsOverloadResolutionForMoveAssignment()) && - "move assignment should not be deleted"); - data().DefaultedMoveAssignmentIsDeleted = true; - } - - /// \brief Determine whether this class should get an implicit move - /// assignment operator or if any existing special member function inhibits - /// this. - bool needsImplicitMoveAssignment() const { - return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) && - !hasUserDeclaredCopyConstructor() && - !hasUserDeclaredCopyAssignment() && - !hasUserDeclaredMoveConstructor() && - !hasUserDeclaredDestructor(); - } - - /// \brief Determine whether we need to eagerly declare a move assignment - /// operator for this class. - bool needsOverloadResolutionForMoveAssignment() const { - return data().NeedOverloadResolutionForMoveAssignment; - } - - /// \brief Determine whether this class has a user-declared destructor. - /// - /// When false, a destructor will be implicitly declared. - bool hasUserDeclaredDestructor() const { - return data().UserDeclaredSpecialMembers & SMF_Destructor; - } - - /// \brief Determine whether this class needs an implicit destructor to - /// be lazily declared. - bool needsImplicitDestructor() const { - return !(data().DeclaredSpecialMembers & SMF_Destructor); - } - - /// \brief Determine whether we need to eagerly declare a destructor for this - /// class. - bool needsOverloadResolutionForDestructor() const { - return data().NeedOverloadResolutionForDestructor; - } - - /// \brief Determine whether this class describes a lambda function object. - bool isLambda() const { - // An update record can't turn a non-lambda into a lambda. - auto *DD = DefinitionData.getNotUpdated(); - return DD && DD->IsLambda; - } - - /// \brief Determine whether this class describes a generic - /// lambda function object (i.e. function call operator is - /// a template). - bool isGenericLambda() const; - - /// \brief Retrieve the lambda call operator of the closure type - /// if this is a closure type. - CXXMethodDecl *getLambdaCallOperator() const; - - /// \brief Retrieve the lambda static invoker, the address of which - /// is returned by the conversion operator, and the body of which - /// is forwarded to the lambda call operator. - CXXMethodDecl *getLambdaStaticInvoker() const; - - /// \brief Retrieve the generic lambda's template parameter list. - /// Returns null if the class does not represent a lambda or a generic - /// lambda. - TemplateParameterList *getGenericLambdaTemplateParameterList() const; - - LambdaCaptureDefault getLambdaCaptureDefault() const { - assert(isLambda()); - return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); - } - - /// \brief For a closure type, retrieve the mapping from captured - /// variables and \c this to the non-static data members that store the - /// values or references of the captures. - /// - /// \param Captures Will be populated with the mapping from captured - /// variables to the corresponding fields. - /// - /// \param ThisCapture Will be set to the field declaration for the - /// \c this capture. - /// - /// \note No entries will be added for init-captures, as they do not capture - /// variables. - void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, - FieldDecl *&ThisCapture) const; - - typedef const LambdaCapture *capture_const_iterator; - typedef llvm::iterator_range<capture_const_iterator> capture_const_range; - - capture_const_range captures() const { - return capture_const_range(captures_begin(), captures_end()); - } - capture_const_iterator captures_begin() const { - return isLambda() ? getLambdaData().Captures : nullptr; - } - capture_const_iterator captures_end() const { - return isLambda() ? captures_begin() + getLambdaData().NumCaptures - : nullptr; - } - - typedef UnresolvedSetIterator conversion_iterator; - conversion_iterator conversion_begin() const { - return data().Conversions.get(getASTContext()).begin(); - } - conversion_iterator conversion_end() const { - return data().Conversions.get(getASTContext()).end(); - } - - /// 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. - void removeConversion(const NamedDecl *Old); - - /// \brief Get all conversion functions visible in current class, - /// including conversion function templates. - llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions(); - - /// Determine 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; } - - /// \brief Whether this class has any in-class initializers - /// for non-static data members (including those in anonymous unions or - /// structs). - bool hasInClassInitializer() const { return data().HasInClassInitializer; } - - /// \brief Whether this class or any of its subobjects has any members of - /// reference type which would make value-initialization ill-formed. - /// - /// Per C++03 [dcl.init]p5: - /// - if T is a non-union class type without a user-declared constructor, - /// then every non-static data member and base-class component of T is - /// value-initialized [...] A program that calls for [...] - /// value-initialization of an entity of reference type is ill-formed. - bool hasUninitializedReferenceMember() const { - return !isUnion() && !hasUserDeclaredConstructor() && - data().HasUninitializedReferenceMember; - } - - /// \brief Whether this class is a POD-type (C++ [class]p4) - /// - /// For purposes of this function a class is POD if it 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. - /// - /// Note that this is the C++ TR1 definition of POD. - bool isPOD() const { return data().PlainOldData; } - - /// \brief True if this class is C-like, without C++-specific features, e.g. - /// it contains only public fields, no bases, tag kind is not 'class', etc. - bool isCLike() const; - - /// \brief Determine whether this is an empty class in the sense of - /// (C++11 [meta.unary.prop]). - /// - /// A non-union class is empty iff it has a virtual function, virtual base, - /// data member (other than 0-width bit-field) or inherits from a non-empty - /// class. - /// - /// \note This does NOT include a check for union-ness. - bool isEmpty() const { return data().Empty; } - - /// 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; } - - /// \brief Determine whether this class has a pure virtual function. - /// - /// The class is is abstract per (C++ [class.abstract]p2) if it declares - /// a pure virtual function or inherits a pure virtual function that is - /// not overridden. - bool isAbstract() const { return data().Abstract; } - - /// \brief Determine whether this class has standard layout per - /// (C++ [class]p7) - bool isStandardLayout() const { return data().IsStandardLayout; } - - /// \brief Determine whether this class, or any of its class subobjects, - /// contains a mutable field. - bool hasMutableFields() const { return data().HasMutableFields; } - - /// \brief Determine whether this class has any variant members. - bool hasVariantMembers() const { return data().HasVariantMembers; } - - /// \brief Determine whether this class has a trivial default constructor - /// (C++11 [class.ctor]p5). - bool hasTrivialDefaultConstructor() const { - return hasDefaultConstructor() && - (data().HasTrivialSpecialMembers & SMF_DefaultConstructor); - } - - /// \brief Determine whether this class has a non-trivial default constructor - /// (C++11 [class.ctor]p5). - bool hasNonTrivialDefaultConstructor() const { - return (data().DeclaredNonTrivialSpecialMembers & SMF_DefaultConstructor) || - (needsImplicitDefaultConstructor() && - !(data().HasTrivialSpecialMembers & SMF_DefaultConstructor)); - } - - /// \brief Determine whether this class has at least one constexpr constructor - /// other than the copy or move constructors. - bool hasConstexprNonCopyMoveConstructor() const { - return data().HasConstexprNonCopyMoveConstructor || - (needsImplicitDefaultConstructor() && - defaultedDefaultConstructorIsConstexpr()); - } - - /// \brief Determine whether a defaulted default constructor for this class - /// would be constexpr. - bool defaultedDefaultConstructorIsConstexpr() const { - return data().DefaultedDefaultConstructorIsConstexpr && - (!isUnion() || hasInClassInitializer() || !hasVariantMembers()); - } - - /// \brief Determine whether this class has a constexpr default constructor. - bool hasConstexprDefaultConstructor() const { - return data().HasConstexprDefaultConstructor || - (needsImplicitDefaultConstructor() && - defaultedDefaultConstructorIsConstexpr()); - } - - /// \brief Determine whether this class has a trivial copy constructor - /// (C++ [class.copy]p6, C++11 [class.copy]p12) - bool hasTrivialCopyConstructor() const { - return data().HasTrivialSpecialMembers & SMF_CopyConstructor; - } - - /// \brief Determine whether this class has a non-trivial copy constructor - /// (C++ [class.copy]p6, C++11 [class.copy]p12) - bool hasNonTrivialCopyConstructor() const { - return data().DeclaredNonTrivialSpecialMembers & SMF_CopyConstructor || - !hasTrivialCopyConstructor(); - } - - /// \brief Determine whether this class has a trivial move constructor - /// (C++11 [class.copy]p12) - bool hasTrivialMoveConstructor() const { - return hasMoveConstructor() && - (data().HasTrivialSpecialMembers & SMF_MoveConstructor); - } - - /// \brief Determine whether this class has a non-trivial move constructor - /// (C++11 [class.copy]p12) - bool hasNonTrivialMoveConstructor() const { - return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveConstructor) || - (needsImplicitMoveConstructor() && - !(data().HasTrivialSpecialMembers & SMF_MoveConstructor)); - } - - /// \brief Determine whether this class has a trivial copy assignment operator - /// (C++ [class.copy]p11, C++11 [class.copy]p25) - bool hasTrivialCopyAssignment() const { - return data().HasTrivialSpecialMembers & SMF_CopyAssignment; - } - - /// \brief Determine whether this class has a non-trivial copy assignment - /// operator (C++ [class.copy]p11, C++11 [class.copy]p25) - bool hasNonTrivialCopyAssignment() const { - return data().DeclaredNonTrivialSpecialMembers & SMF_CopyAssignment || - !hasTrivialCopyAssignment(); - } - - /// \brief Determine whether this class has a trivial move assignment operator - /// (C++11 [class.copy]p25) - bool hasTrivialMoveAssignment() const { - return hasMoveAssignment() && - (data().HasTrivialSpecialMembers & SMF_MoveAssignment); - } - - /// \brief Determine whether this class has a non-trivial move assignment - /// operator (C++11 [class.copy]p25) - bool hasNonTrivialMoveAssignment() const { - return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveAssignment) || - (needsImplicitMoveAssignment() && - !(data().HasTrivialSpecialMembers & SMF_MoveAssignment)); - } - - /// \brief Determine whether this class has a trivial destructor - /// (C++ [class.dtor]p3) - bool hasTrivialDestructor() const { - return data().HasTrivialSpecialMembers & SMF_Destructor; - } - - /// \brief Determine whether this class has a non-trivial destructor - /// (C++ [class.dtor]p3) - bool hasNonTrivialDestructor() const { - return !(data().HasTrivialSpecialMembers & SMF_Destructor); - } - - /// \brief Determine whether this class has a destructor which has no - /// semantic effect. - /// - /// Any such destructor will be trivial, public, defaulted and not deleted, - /// and will call only irrelevant destructors. - bool hasIrrelevantDestructor() const { - return data().HasIrrelevantDestructor; - } - - /// \brief Determine whether this class has a non-literal or/ volatile type - /// non-static data member or base class. - bool hasNonLiteralTypeFieldsOrBases() const { - return data().HasNonLiteralTypeFieldsOrBases; - } - - /// \brief Determine whether this class is considered trivially copyable per - /// (C++11 [class]p6). - bool isTriviallyCopyable() const; - - /// \brief Determine whether this class is considered trivial. - /// - /// C++11 [class]p6: - /// "A trivial class is a class that has a trivial default constructor and - /// is trivially copiable." - bool isTrivial() const { - return isTriviallyCopyable() && hasTrivialDefaultConstructor(); - } - - /// \brief Determine whether this class is a literal type. - /// - /// C++11 [basic.types]p10: - /// A class type that has all the following properties: - /// - it has a trivial destructor - /// - every constructor call and full-expression in the - /// brace-or-equal-intializers for non-static data members (if any) is - /// a constant expression. - /// - it is an aggregate type or has at least one constexpr constructor - /// or constructor template that is not a copy or move constructor, and - /// - all of its non-static data members and base classes are of literal - /// types - /// - /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by - /// treating types with trivial default constructors as literal types. - bool isLiteral() const { - return hasTrivialDestructor() && - (isAggregate() || hasConstexprNonCopyMoveConstructor() || - hasTrivialDefaultConstructor()) && - !hasNonLiteralTypeFieldsOrBases(); - } - - /// \brief If this record is an instantiation of a member class, - /// retrieves the member class from which it was instantiated. - /// - /// This routine will return non-null for (non-templated) member - /// classes of class templates. For example, given: - /// - /// \code - /// template<typename T> - /// struct X { - /// struct A { }; - /// }; - /// \endcode - /// - /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl - /// whose parent is the class template specialization X<int>. For - /// this declaration, getInstantiatedFromMemberClass() will return - /// the CXXRecordDecl X<T>::A. When a complete definition of - /// X<int>::A is required, it will be instantiated from the - /// declaration returned by getInstantiatedFromMemberClass(). - CXXRecordDecl *getInstantiatedFromMemberClass() const; - - /// \brief If this class is an instantiation of a member class of a - /// class template specialization, retrieves the member specialization - /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const; - - /// \brief Specify that this record is an instantiation of the - /// member class \p RD. - void setInstantiationOfMemberClass(CXXRecordDecl *RD, - TemplateSpecializationKind TSK); - - /// \brief Retrieves the class template that is described by this - /// class declaration. - /// - /// Every class template is represented as a ClassTemplateDecl and a - /// CXXRecordDecl. The former contains template properties (such as - /// the template parameter lists) while the latter contains the - /// actual description of the template's - /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the - /// CXXRecordDecl that from a ClassTemplateDecl, while - /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from - /// a CXXRecordDecl. - ClassTemplateDecl *getDescribedClassTemplate() const; - - void setDescribedClassTemplate(ClassTemplateDecl *Template); - - /// \brief Determine whether this particular class is a specialization or - /// instantiation of a class template or member class of a class template, - /// and how it was instantiated or specialized. - TemplateSpecializationKind getTemplateSpecializationKind() const; - - /// \brief Set the kind of specialization or template instantiation this is. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK); - - /// \brief Retrieve the record declaration from which this record could be - /// instantiated. Returns null if this class is not a template instantiation. - const CXXRecordDecl *getTemplateInstantiationPattern() const; - - CXXRecordDecl *getTemplateInstantiationPattern() { - return const_cast<CXXRecordDecl *>(const_cast<const CXXRecordDecl *>(this) - ->getTemplateInstantiationPattern()); - } - - /// \brief Returns the destructor decl for this class. - CXXDestructorDecl *getDestructor() const; - - /// \brief Returns true if the class destructor, or any implicitly invoked - /// destructors are marked noreturn. - bool isAnyDestructorNoReturn() const; - - /// \brief If the class is a local class [class.local], returns - /// the enclosing function declaration. - const FunctionDecl *isLocalClass() const { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext())) - return RD->isLocalClass(); - - return dyn_cast<FunctionDecl>(getDeclContext()); - } - - FunctionDecl *isLocalClass() { - return const_cast<FunctionDecl*>( - const_cast<const CXXRecordDecl*>(this)->isLocalClass()); - } - - /// \brief Determine whether this dependent class is a current instantiation, - /// when viewed from within the given context. - bool isCurrentInstantiation(const DeclContext *CurContext) const; - - /// \brief Determine whether this class is derived from the class \p Base. - /// - /// This routine only determines whether this class is derived from \p Base, - /// but does not account for factors that may make a Derived -> Base class - /// ill-formed, such as private/protected inheritance or multiple, ambiguous - /// base class subobjects. - /// - /// \param Base the base class we are searching for. - /// - /// \returns true if this class is derived from Base, false otherwise. - bool isDerivedFrom(const CXXRecordDecl *Base) const; - - /// \brief Determine whether this class is derived from the type \p Base. - /// - /// This routine only determines whether this class is derived from \p Base, - /// but does not account for factors that may make a Derived -> Base class - /// ill-formed, such as private/protected inheritance or multiple, ambiguous - /// base class subobjects. - /// - /// \param Base the base class we are searching for. - /// - /// \param Paths will contain the paths taken from the current class to the - /// given \p Base class. - /// - /// \returns true if this class is derived from \p Base, false otherwise. - /// - /// \todo add a separate parameter to configure IsDerivedFrom, rather than - /// tangling input and output in \p Paths - bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; - - /// \brief Determine whether this class is virtually derived from - /// the class \p Base. - /// - /// This routine only determines whether this class is virtually - /// derived from \p Base, but does not account for factors that may - /// make a Derived -> Base class ill-formed, such as - /// private/protected inheritance or multiple, ambiguous base class - /// subobjects. - /// - /// \param Base the base class we are searching for. - /// - /// \returns true if this class is virtually derived from Base, - /// false otherwise. - bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const; - - /// \brief Determine whether this class is provably not derived from - /// the type \p Base. - bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const; - - /// \brief Function type used by forallBases() as a callback. - /// - /// \param BaseDefinition the definition of the base class - /// - /// \returns true if this base matched the search criteria - typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)> - ForallBasesCallback; - - /// \brief Determines if the given callback holds for all the direct - /// or indirect base classes of this type. - /// - /// The class itself does not count as a base class. This routine - /// returns false if the class has non-computable base classes. - /// - /// \param BaseMatches Callback invoked for each (direct or indirect) base - /// class of this type, or if \p AllowShortCircuit is true then until a call - /// returns false. - /// - /// \param AllowShortCircuit if false, forces the callback to be called - /// for every base class, even if a dependent or non-matching base was - /// found. - bool forallBases(ForallBasesCallback BaseMatches, - bool AllowShortCircuit = true) const; - - /// \brief Function type used by lookupInBases() to determine whether a - /// specific base class subobject matches the lookup criteria. - /// - /// \param Specifier the base-class specifier that describes the inheritance - /// from the base class we are trying to match. - /// - /// \param Path the current path, from the most-derived class down to the - /// base named by the \p Specifier. - /// - /// \returns true if this base matched the search criteria, false otherwise. - typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path)> BaseMatchesCallback; - - /// \brief Look for entities within the base classes of this C++ class, - /// transitively searching all base class subobjects. - /// - /// This routine uses the callback function \p BaseMatches to find base - /// classes meeting some search criteria, walking all base class subobjects - /// and populating the given \p Paths structure with the paths through the - /// inheritance hierarchy that resulted in a match. On a successful search, - /// the \p Paths structure can be queried to retrieve the matching paths and - /// to determine if there were any ambiguities. - /// - /// \param BaseMatches callback function used to determine whether a given - /// base matches the user-defined search criteria. - /// - /// \param Paths used to record the paths from this class to its base class - /// subobjects that match the search criteria. - /// - /// \returns true if there exists any path from this class to a base class - /// subobject that matches the search criteria. - bool lookupInBases(BaseMatchesCallback BaseMatches, - CXXBasePaths &Paths) const; - - /// \brief Base-class lookup callback that determines whether the given - /// base class specifier refers to a specific class declaration. - /// - /// This callback can be used with \c lookupInBases() to determine whether - /// a given derived class has is a base class subobject of a particular type. - /// The base record pointer should refer to the canonical CXXRecordDecl of the - /// base class that we are searching for. - static bool FindBaseClass(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, const CXXRecordDecl *BaseRecord); - - /// \brief Base-class lookup callback that determines whether the - /// given base class specifier refers to a specific class - /// declaration and describes virtual derivation. - /// - /// This callback can be used with \c lookupInBases() to determine - /// whether a given derived class has is a virtual base class - /// subobject of a particular type. The base record pointer should - /// refer to the canonical CXXRecordDecl of the base class that we - /// are searching for. - static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - const CXXRecordDecl *BaseRecord); - - /// \brief Base-class lookup callback that determines whether there exists - /// a tag with the given name. - /// - /// This callback can be used with \c lookupInBases() to find tag members - /// of the given name within a C++ class hierarchy. - static bool FindTagMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name); - - /// \brief Base-class lookup callback that determines whether there exists - /// a member with the given name. - /// - /// This callback can be used with \c lookupInBases() to find members - /// of the given name within a C++ class hierarchy. - static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name); - - /// \brief Base-class lookup callback that determines whether there exists - /// a member with the given name that can be used in a nested-name-specifier. - /// - /// This callback can be used with \c lookupInBases() to find members of - /// the given name within a C++ class hierarchy that can occur within - /// nested-name-specifiers. - static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name); - - /// \brief Retrieve the final overriders for each virtual member - /// function in the class hierarchy where this class is the - /// 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; - - /// Renders and displays an inheritance diagram - /// for this C++ class and all of its base classes (transitively) using - /// GraphViz. - void viewInheritance(ASTContext& Context) const; - - /// \brief Calculates the access of a decl that is reached - /// along a path. - static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, - AccessSpecifier DeclAccess) { - assert(DeclAccess != AS_none); - if (DeclAccess == AS_private) return AS_none; - return (PathAccess > DeclAccess ? PathAccess : DeclAccess); - } - - /// \brief Indicates that the declaration of a defaulted or deleted special - /// member function is now complete. - void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD); - - /// \brief Indicates that the definition of this class is now complete. - void completeDefinition() override; - - /// \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; - - /// \brief If this is the closure type of a lambda expression, retrieve the - /// number to be used for name mangling in the Itanium C++ ABI. - /// - /// Zero indicates that this closure type has internal linkage, so the - /// mangling number does not matter, while a non-zero value indicates which - /// lambda expression this is in this particular context. - unsigned getLambdaManglingNumber() const { - assert(isLambda() && "Not a lambda closure type!"); - return getLambdaData().ManglingNumber; - } - - /// \brief Retrieve the declaration that provides additional context for a - /// lambda, when the normal declaration context is not specific enough. - /// - /// Certain contexts (default arguments of in-class function parameters and - /// the initializers of data members) have separate name mangling rules for - /// lambdas within the Itanium C++ ABI. For these cases, this routine provides - /// the declaration in which the lambda occurs, e.g., the function parameter - /// or the non-static data member. Otherwise, it returns NULL to imply that - /// the declaration context suffices. - Decl *getLambdaContextDecl() const { - assert(isLambda() && "Not a lambda closure type!"); - return getLambdaData().ContextDecl; - } - - /// \brief Set the mangling number and context declaration for a lambda - /// class. - void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) { - getLambdaData().ManglingNumber = ManglingNumber; - getLambdaData().ContextDecl = ContextDecl; - } - - /// \brief Returns the inheritance model used for this record. - MSInheritanceAttr::Spelling getMSInheritanceModel() const; - /// \brief Calculate what the inheritance model would be for this class. - MSInheritanceAttr::Spelling calculateInheritanceModel() const; - - /// In the Microsoft C++ ABI, use zero for the field offset of a null data - /// member pointer if we can guarantee that zero is not a valid field offset, - /// or if the member pointer has multiple fields. Polymorphic classes have a - /// vfptr at offset zero, so we can use zero for null. If there are multiple - /// fields, we can use zero even if it is a valid field offset because - /// null-ness testing will check the other fields. - bool nullFieldOffsetIsZero() const { - return !MSInheritanceAttr::hasOnlyOneField(/*IsMemberFunction=*/false, - getMSInheritanceModel()) || - (hasDefinition() && isPolymorphic()); - } - - /// \brief Controls when vtordisps will be emitted if this record is used as a - /// virtual base. - MSVtorDispAttr::Mode getMSVtorDispMode() const; - - /// \brief Determine whether this lambda expression was known to be dependent - /// at the time it was created, even if its context does not appear to be - /// dependent. - /// - /// This flag is a workaround for an issue with parsing, where default - /// arguments are parsed before their enclosing function declarations have - /// been created. This means that any lambda expressions within those - /// default arguments will have as their DeclContext the context enclosing - /// the function declaration, which may be non-dependent even when the - /// function declaration itself is dependent. This flag indicates when we - /// know that the lambda is dependent despite that. - bool isDependentLambda() const { - return isLambda() && getLambdaData().Dependent; - } - - TypeSourceInfo *getLambdaTypeInfo() const { - return getLambdaData().MethodTyInfo; - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstCXXRecord && K <= lastCXXRecord; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend class ASTReader; - friend class ASTWriter; -}; - -/// \brief Represents a static or instance method of a struct/union/class. -/// -/// In the terminology of the C++ Standard, these are the (static and -/// non-static) member functions, whether virtual or not. -class CXXMethodDecl : public FunctionDecl { - void anchor() override; -protected: - CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInline, - bool isConstexpr, SourceLocation EndLocation) - : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, - SC, isInline, isConstexpr) { - if (EndLocation.isValid()) - setRangeEnd(EndLocation); - } - -public: - static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, - bool isInline, - bool isConstexpr, - SourceLocation EndLocation); - - static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - bool isStatic() const; - bool isInstance() const { return !isStatic(); } - - /// Returns true if the given operator is implicitly static in a record - /// context. - static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) { - // [class.free]p1: - // Any allocation function for a class T is a static member - // (even if not explicitly declared static). - // [class.free]p6 Any deallocation function for a class X is a static member - // (even if not explicitly declared static). - return OOK == OO_New || OOK == OO_Array_New || OOK == OO_Delete || - OOK == OO_Array_Delete; - } - - bool isConst() const { return getType()->castAs<FunctionType>()->isConst(); } - bool isVolatile() const { return getType()->castAs<FunctionType>()->isVolatile(); } - - bool isVirtual() const { - CXXMethodDecl *CD = - cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); - - // Member function is virtual if it is marked explicitly so, or if it is - // declared in __interface -- then it is automatically pure virtual. - if (CD->isVirtualAsWritten() || CD->isPure()) - return true; - - return (CD->begin_overridden_methods() != CD->end_overridden_methods()); - } - - /// \brief Determine whether this is a usual deallocation function - /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded - /// delete or delete[] operator with a particular signature. - bool isUsualDeallocationFunction() const; - - /// \brief Determine whether this is a copy-assignment operator, regardless - /// of whether it was declared implicitly or explicitly. - bool isCopyAssignmentOperator() const; - - /// \brief Determine whether this is a move assignment operator. - bool isMoveAssignmentOperator() const; - - CXXMethodDecl *getCanonicalDecl() override { - return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); - } - const CXXMethodDecl *getCanonicalDecl() const { - return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl(); - } - - CXXMethodDecl *getMostRecentDecl() { - return cast<CXXMethodDecl>( - static_cast<FunctionDecl *>(this)->getMostRecentDecl()); - } - const CXXMethodDecl *getMostRecentDecl() const { - return const_cast<CXXMethodDecl*>(this)->getMostRecentDecl(); - } - - /// True if this method is user-declared and was not - /// deleted or defaulted on its first declaration. - bool isUserProvided() const { - return !(isDeleted() || getCanonicalDecl()->isDefaulted()); - } - - /// - void addOverriddenMethod(const CXXMethodDecl *MD); - - typedef const CXXMethodDecl *const* method_iterator; - - method_iterator begin_overridden_methods() const; - method_iterator end_overridden_methods() const; - unsigned size_overridden_methods() const; - - /// Returns the parent of this method declaration, which - /// is the class in which this method is defined. - const CXXRecordDecl *getParent() const { - return cast<CXXRecordDecl>(FunctionDecl::getParent()); - } - - /// Returns the parent of this method declaration, which - /// is the class in which this method is defined. - CXXRecordDecl *getParent() { - return const_cast<CXXRecordDecl *>( - cast<CXXRecordDecl>(FunctionDecl::getParent())); - } - - /// \brief Returns the type of the \c this pointer. - /// - /// Should only be called for instance (i.e., non-static) methods. - QualType getThisType(ASTContext &C) const; - - unsigned getTypeQualifiers() const { - 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(); - /// }; - /// @endcode - RefQualifierKind getRefQualifier() const { - return getType()->getAs<FunctionProtoType>()->getRefQualifier(); - } - - bool hasInlineBody() const; - - /// \brief Determine whether this is a lambda closure type's static member - /// function that is used for the result of the lambda's conversion to - /// function pointer (for a lambda with no captures). - /// - /// The function itself, if used, will have a placeholder body that will be - /// supplied by IR generation to either forward to the function call operator - /// or clone the function call operator. - bool isLambdaStaticInvoker() const; - - /// \brief Find the method in \p RD that corresponds to this one. - /// - /// Find if \p RD or one of the classes it inherits from override this method. - /// If so, return it. \p RD is assumed to be a subclass of the class defining - /// this method (or be the class itself), unless \p MayBeBase is set to true. - CXXMethodDecl * - getCorrespondingMethodInClass(const CXXRecordDecl *RD, - bool MayBeBase = false); - - const CXXMethodDecl * - getCorrespondingMethodInClass(const CXXRecordDecl *RD, - bool MayBeBase = false) const { - return const_cast<CXXMethodDecl *>(this) - ->getCorrespondingMethodInClass(RD, MayBeBase); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstCXXMethod && K <= lastCXXMethod; - } -}; - -/// \brief Represents a C++ base or member initializer. -/// -/// This 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 -/// initializers: -/// -/// \code -/// class A { }; -/// class B : public A { -/// float f; -/// public: -/// B(A& a) : A(a), f(3.14159) { } -/// }; -/// \endcode -class CXXCtorInitializer final - : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> { - /// \brief Either the base class name/delegating constructor type (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 or, for a base initializer - /// pack expansion, the location of the ellipsis. - /// - /// In the case of a delegating - /// constructor, it will still include the type's source location as the - /// Initializee points to the CXXConstructorDecl (to allow loop detection). - 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 Location of the left paren of the ctor-initializer. - SourceLocation LParenLoc; - - /// \brief Location of the right paren of the ctor-initializer. - SourceLocation RParenLoc; - - /// \brief If the initializee is a type, whether that type makes this - /// a delegating initialization. - bool IsDelegating : 1; - - /// \brief If the initializer is a base initializer, this keeps track - /// of whether the base is virtual or not. - bool IsVirtual : 1; - - /// \brief Whether or not the initializer is explicitly written - /// in the sources. - bool IsWritten : 1; - - /// If IsWritten is true, then this number keeps track of the textual order - /// of this initializer in the original sources, counting from 0; otherwise, - /// it stores the number of array index variables stored after this object - /// in memory. - unsigned SourceOrderOrNumArrayIndices : 13; - - CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, Expr *Init, - SourceLocation R, VarDecl **Indices, unsigned NumIndices); - -public: - /// \brief Creates a new base-class initializer. - explicit - CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, - SourceLocation L, Expr *Init, SourceLocation R, - SourceLocation EllipsisLoc); - - /// \brief Creates a new member initializer. - explicit - CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, Expr *Init, - SourceLocation R); - - /// \brief Creates a new anonymous field initializer. - explicit - CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, Expr *Init, - SourceLocation R); - - /// \brief Creates a new delegating initializer. - explicit - CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, - SourceLocation L, Expr *Init, SourceLocation R); - - /// \brief Creates a new member initializer that optionally contains - /// array indices used to describe an elementwise initialization. - static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, - SourceLocation MemberLoc, SourceLocation L, - Expr *Init, SourceLocation R, - VarDecl **Indices, unsigned NumIndices); - - /// \brief Determine whether this initializer is initializing a base class. - bool isBaseInitializer() const { - return Initializee.is<TypeSourceInfo*>() && !IsDelegating; - } - - /// \brief Determine whether this initializer is initializing a non-static - /// data member. - 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 an implicit initializer - /// generated for a field with an initializer defined on the member - /// declaration. - /// - /// In-class member initializers (also known as "non-static data member - /// initializations", NSDMIs) were introduced in C++11. - bool isInClassMemberInitializer() const { - return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass; - } - - /// \brief Determine whether this initializer is creating a delegating - /// constructor. - bool isDelegatingInitializer() const { - return Initializee.is<TypeSourceInfo*>() && IsDelegating; - } - - /// \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. - TypeLoc getBaseClassLoc() const; - - /// If this is a base class initializer, returns the type of the base class. - /// Otherwise, returns null. - const Type *getBaseClass() const; - - /// Returns whether the base is virtual or not. - bool isBaseVirtual() const { - assert(isBaseInitializer() && "Must call this on base initializer!"); - - return IsVirtual; - } - - /// \brief Returns the declarator information for a base class or delegating - /// initializer. - TypeSourceInfo *getTypeSourceInfo() const { - return Initializee.dyn_cast<TypeSourceInfo *>(); - } - - /// \brief If this is a member initializer, returns the declaration of the - /// non-static data member being initialized. Otherwise, returns null. - FieldDecl *getMember() const { - if (isMemberInitializer()) - return Initializee.get<FieldDecl*>(); - return nullptr; - } - FieldDecl *getAnyMember() const { - if (isMemberInitializer()) - return Initializee.get<FieldDecl*>(); - if (isIndirectMemberInitializer()) - return Initializee.get<IndirectFieldDecl*>()->getAnonField(); - return nullptr; - } - - IndirectFieldDecl *getIndirectMember() const { - if (isIndirectMemberInitializer()) - return Initializee.get<IndirectFieldDecl*>(); - return nullptr; - } - - SourceLocation getMemberLocation() const { - return MemberOrEllipsisLocation; - } - - /// \brief Determine the source location of the initializer. - SourceLocation getSourceLocation() const; - - /// \brief Determine the source range covering the entire initializer. - SourceRange getSourceRange() const LLVM_READONLY; - - /// \brief Determine whether this initializer is explicitly written - /// in the source code. - bool isWritten() const { return IsWritten; } - - /// \brief Return the source position of the initializer, counting from 0. - /// If the initializer was implicit, -1 is returned. - int getSourceOrder() const { - return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1; - } - - /// \brief Set the source order of this initializer. - /// - /// This can only be called once for each initializer; it cannot be called - /// on an initializer having a positive number of (implicit) array indices. - /// - /// This assumes that the initializer was written in the source code, and - /// ensures that isWritten() returns true. - void setSourceOrder(int pos) { - assert(!IsWritten && - "calling twice setSourceOrder() on the same initializer"); - assert(SourceOrderOrNumArrayIndices == 0 && - "setSourceOrder() used when there are implicit array indices"); - assert(pos >= 0 && - "setSourceOrder() used to make an initializer implicit"); - IsWritten = true; - SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); - } - - SourceLocation getLParenLoc() const { return LParenLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - /// \brief Determine the number of implicit array indices used while - /// described an array member initialization. - unsigned getNumArrayIndices() const { - return IsWritten ? 0 : SourceOrderOrNumArrayIndices; - } - - /// \brief Retrieve a particular array index variable used to - /// describe an array member initialization. - VarDecl *getArrayIndex(unsigned I) { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return getTrailingObjects<VarDecl *>()[I]; - } - const VarDecl *getArrayIndex(unsigned I) const { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return getTrailingObjects<VarDecl *>()[I]; - } - void setArrayIndex(unsigned I, VarDecl *Index) { - assert(I < getNumArrayIndices() && "Out of bounds member array index"); - getTrailingObjects<VarDecl *>()[I] = Index; - } - ArrayRef<VarDecl *> getArrayIndexes() { - assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); - return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(), - getNumArrayIndices()); - } - - /// \brief Get the initializer. - Expr *getInit() const { return static_cast<Expr*>(Init); } - - friend TrailingObjects; -}; - -/// \brief Represents a C++ constructor within a class. -/// -/// For example: -/// -/// \code -/// class X { -/// public: -/// explicit X(int); // represented by a CXXConstructorDecl. -/// }; -/// \endcode -class CXXConstructorDecl : public CXXMethodDecl { - void anchor() override; - /// \brief Whether this constructor declaration has the \c explicit keyword - /// specified. - bool IsExplicitSpecified : 1; - - /// \name Support for base and member initializers. - /// \{ - /// \brief The arguments used to initialize the base or member. - LazyCXXCtorInitializersPtr CtorInitializers; - unsigned NumCtorInitializers; - /// \} - - CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isExplicitSpecified, bool isInline, - bool isImplicitlyDeclared, bool isConstexpr) - : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, isConstexpr, SourceLocation()), - IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr), - NumCtorInitializers(0) { - setImplicit(isImplicitlyDeclared); - } - -public: - static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID); - static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isExplicit, - bool isInline, bool isImplicitlyDeclared, - bool isConstexpr); - - /// \brief Determine whether this constructor declaration has the - /// \c explicit keyword specified. - bool isExplicitSpecified() const { return IsExplicitSpecified; } - - /// \brief Determine whether this constructor was marked "explicit" or not. - bool isExplicit() const { - return cast<CXXConstructorDecl>(getFirstDecl())->isExplicitSpecified(); - } - - /// \brief Iterates through the member/base initializer list. - typedef CXXCtorInitializer **init_iterator; - - /// \brief Iterates through the member/base initializer list. - typedef CXXCtorInitializer *const *init_const_iterator; - - typedef llvm::iterator_range<init_iterator> init_range; - typedef llvm::iterator_range<init_const_iterator> init_const_range; - - init_range inits() { return init_range(init_begin(), init_end()); } - init_const_range inits() const { - return init_const_range(init_begin(), init_end()); - } - - /// \brief Retrieve an iterator to the first initializer. - init_iterator init_begin() { - const auto *ConstThis = this; - return const_cast<init_iterator>(ConstThis->init_begin()); - } - /// \brief Retrieve an iterator to the first initializer. - init_const_iterator init_begin() const; - - /// \brief Retrieve an iterator past the last initializer. - init_iterator init_end() { - return init_begin() + NumCtorInitializers; - } - /// \brief Retrieve an iterator past the last initializer. - init_const_iterator init_end() const { - return init_begin() + 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()); - } - - /// \brief Determine the number of arguments used to initialize the member - /// or base. - unsigned getNumCtorInitializers() const { - return NumCtorInitializers; - } - - void setNumCtorInitializers(unsigned numCtorInitializers) { - NumCtorInitializers = numCtorInitializers; - } - - void setCtorInitializers(CXXCtorInitializer **Initializers) { - CtorInitializers = Initializers; - } - - /// \brief Determine whether this constructor is a delegating constructor. - bool isDelegatingConstructor() const { - return (getNumCtorInitializers() == 1) && - init_begin()[0]->isDelegatingInitializer(); - } - - /// \brief When this constructor delegates to another, retrieve the target. - CXXConstructorDecl *getTargetConstructor() const; - - /// Whether this constructor is a default - /// constructor (C++ [class.ctor]p5), which can be used to - /// default-initialize a class of this type. - bool isDefaultConstructor() const; - - /// \brief Whether this constructor is a copy constructor (C++ [class.copy]p2, - /// which can be used to copy the class. - /// - /// \p TypeQuals will be set to the qualifiers on the - /// argument type. For example, \p TypeQuals would be set to \c - /// Qualifiers::Const for the following copy constructor: - /// - /// \code - /// class X { - /// public: - /// X(const X&); - /// }; - /// \endcode - bool isCopyConstructor(unsigned &TypeQuals) const; - - /// Whether this constructor is a copy - /// constructor (C++ [class.copy]p2, which can be used to copy the - /// class. - bool isCopyConstructor() const { - unsigned TypeQuals = 0; - return isCopyConstructor(TypeQuals); - } - - /// \brief Determine whether this constructor is a move constructor - /// (C++11 [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++11 [class.copy]p3), which can be used to move values of the class. - bool isMoveConstructor() const { - unsigned TypeQuals = 0; - return isMoveConstructor(TypeQuals); - } - - /// \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); - } - - /// 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 - /// would copy the object to itself. Such constructors are never used to copy - /// an object. - 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); - - CXXConstructorDecl *getCanonicalDecl() override { - return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl()); - } - const CXXConstructorDecl *getCanonicalDecl() const { - return const_cast<CXXConstructorDecl*>(this)->getCanonicalDecl(); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == CXXConstructor; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a C++ destructor within a class. -/// -/// For example: -/// -/// \code -/// class X { -/// public: -/// ~X(); // represented by a CXXDestructorDecl. -/// }; -/// \endcode -class CXXDestructorDecl : public CXXMethodDecl { - void anchor() override; - - FunctionDecl *OperatorDelete; - - CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), - OperatorDelete(nullptr) { - setImplicit(isImplicitlyDeclared); - } - -public: - static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo* TInfo, - bool isInline, - bool isImplicitlyDeclared); - static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); - - void setOperatorDelete(FunctionDecl *OD); - const FunctionDecl *getOperatorDelete() const { - return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete; - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == CXXDestructor; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a C++ conversion function within a class. -/// -/// For example: -/// -/// \code -/// class X { -/// public: -/// operator bool(); -/// }; -/// \endcode -class CXXConversionDecl : public CXXMethodDecl { - void anchor() override; - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be applied when the user - /// explicitly wrote a cast. This is a C++11 feature. - bool IsExplicitSpecified : 1; - - CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified, - bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, isConstexpr, EndLocation), - IsExplicitSpecified(isExplicitSpecified) { } - -public: - static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit, - bool isConstexpr, - SourceLocation EndLocation); - static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be used for direct initialization - /// (including explitly written casts). This is a C++11 feature. - bool isExplicitSpecified() const { return IsExplicitSpecified; } - - /// \brief Whether this is an explicit conversion operator (C++11 and later). - /// - /// Explicit conversion operators are only considered for direct - /// initialization, e.g., when the user has explicitly written a cast. - bool isExplicit() const { - return cast<CXXConversionDecl>(getFirstDecl())->isExplicitSpecified(); - } - - /// \brief Returns the type that this conversion function is converting to. - QualType getConversionType() const { - return getType()->getAs<FunctionType>()->getReturnType(); - } - - /// \brief Determine whether this conversion function is a conversion from - /// a lambda closure type to a block pointer. - bool isLambdaToBlockPointerConversion() const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == CXXConversion; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a linkage specification. -/// -/// For example: -/// \code -/// extern "C" void foo(); -/// \endcode -class LinkageSpecDecl : public Decl, public DeclContext { - virtual void anchor(); -public: - /// \brief Represents the language in a linkage specification. - /// - /// The values are part of the serialization ABI for - /// ASTs and cannot be changed without altering that ABI. To help - /// ensure a stable ABI for this, we choose the DW_LANG_ encodings - /// from the dwarf standard. - enum LanguageIDs { - lang_c = /* DW_LANG_C */ 0x0002, - lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 - }; -private: - /// \brief The language for this linkage specification. - unsigned Language : 3; - /// \brief True if this linkage spec has braces. - /// - /// This is needed so that hasBraces() returns the correct result while the - /// linkage spec body is being parsed. Once RBraceLoc has been set this is - /// not used, so it doesn't need to be serialized. - unsigned HasBraces : 1; - /// \brief The source location for the extern keyword. - SourceLocation ExternLoc; - /// \brief The source location for the right brace (if valid). - SourceLocation RBraceLoc; - - LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs lang, bool HasBraces) - : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), - Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc), - RBraceLoc(SourceLocation()) { } - -public: - static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs Lang, - bool HasBraces); - static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// \brief Return the language specified by this linkage specification. - LanguageIDs getLanguage() const { return LanguageIDs(Language); } - /// \brief Set the language specified by this linkage specification. - void setLanguage(LanguageIDs L) { Language = L; } - - /// \brief Determines whether this linkage specification had braces in - /// its syntactic form. - bool hasBraces() const { - assert(!RBraceLoc.isValid() || HasBraces); - return HasBraces; - } - - SourceLocation getExternLoc() const { return ExternLoc; } - SourceLocation getRBraceLoc() const { return RBraceLoc; } - void setExternLoc(SourceLocation L) { ExternLoc = L; } - void setRBraceLoc(SourceLocation L) { - RBraceLoc = L; - HasBraces = RBraceLoc.isValid(); - } - - SourceLocation getLocEnd() const LLVM_READONLY { - if (hasBraces()) - return getRBraceLoc(); - // No braces: get the end location of the (only) declaration in context - // (if present). - return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(ExternLoc, getLocEnd()); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == LinkageSpec; } - static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { - return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D)); - } - static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC)); - } -}; - -/// \brief Represents C++ using-directive. -/// -/// For example: -/// \code -/// using namespace std; -/// \endcode -/// -/// \note UsingDirectiveDecl should be Decl not NamedDecl, but we provide -/// artificial names for all using-directives in order to store -/// them in DeclContext effectively. -class UsingDirectiveDecl : public NamedDecl { - void anchor() override; - /// \brief The location of the \c using keyword. - SourceLocation UsingLoc; - - /// \brief The location of the \c namespace keyword. - SourceLocation NamespaceLoc; - - /// \brief The nested-name-specifier that precedes the namespace. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The namespace nominated by this using-directive. - NamedDecl *NominatedNamespace; - - /// Enclosing context containing both using-directive and nominated - /// namespace. - DeclContext *CommonAncestor; - - /// \brief Returns special DeclarationName used by using-directives. - /// - /// This is only used by DeclContext for storing UsingDirectiveDecls in - /// its lookup structure. - static DeclarationName getName() { - return DeclarationName::getUsingDirectiveName(); - } - - UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceLocation NamespcLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Nominated, - DeclContext *CommonAncestor) - : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), - NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc), - NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } - -public: - /// \brief Retrieve the nested-name-specifier that qualifies the - /// name of the namespace, with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the - /// name of the namespace. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } - const NamedDecl *getNominatedNamespaceAsWritten() const { - return NominatedNamespace; - } - - /// \brief Returns the namespace nominated by this using-directive. - NamespaceDecl *getNominatedNamespace(); - - const NamespaceDecl *getNominatedNamespace() const { - return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); - } - - /// \brief Returns the common ancestor context of this using-directive and - /// its nominated namespace. - DeclContext *getCommonAncestor() { return CommonAncestor; } - const DeclContext *getCommonAncestor() const { return CommonAncestor; } - - /// \brief Return the location of the \c using keyword. - SourceLocation getUsingLoc() const { return UsingLoc; } - - // FIXME: Could omit 'Key' in name. - /// \brief Returns the location of the \c namespace keyword. - SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } - - /// \brief Returns the location of this using declaration's identifier. - SourceLocation getIdentLocation() const { return getLocation(); } - - static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingLoc, - SourceLocation NamespaceLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Nominated, - DeclContext *CommonAncestor); - static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(UsingLoc, getLocation()); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == UsingDirective; } - - // Friend for getUsingDirectiveName. - friend class DeclContext; - - friend class ASTDeclReader; -}; - -/// \brief Represents a C++ namespace alias. -/// -/// For example: -/// -/// \code -/// namespace Foo = Bar; -/// \endcode -class NamespaceAliasDecl : public NamedDecl, - public Redeclarable<NamespaceAliasDecl> { - void anchor() override; - - /// \brief The location of the \c namespace keyword. - SourceLocation NamespaceLoc; - - /// \brief The location of the namespace's identifier. - /// - /// This is accessed by TargetNameLoc. - SourceLocation IdentLoc; - - /// \brief The nested-name-specifier that precedes the namespace. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The Decl that this alias points to, either a NamespaceDecl or - /// a NamespaceAliasDecl. - NamedDecl *Namespace; - - NamespaceAliasDecl(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, SourceLocation AliasLoc, - IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C), - NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), - QualifierLoc(QualifierLoc), Namespace(Namespace) {} - - typedef Redeclarable<NamespaceAliasDecl> redeclarable_base; - NamespaceAliasDecl *getNextRedeclarationImpl() override; - NamespaceAliasDecl *getPreviousDeclImpl() override; - NamespaceAliasDecl *getMostRecentDeclImpl() override; - - friend class ASTDeclReader; - -public: - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Namespace); - - static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - - NamespaceAliasDecl *getCanonicalDecl() override { - return getFirstDecl(); - } - const NamespaceAliasDecl *getCanonicalDecl() const { - return getFirstDecl(); - } - - /// \brief Retrieve the nested-name-specifier that qualifies the - /// name of the namespace, with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the - /// name of the namespace. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief Retrieve the namespace declaration aliased by this directive. - NamespaceDecl *getNamespace() { - if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) - return AD->getNamespace(); - - return cast<NamespaceDecl>(Namespace); - } - - const NamespaceDecl *getNamespace() const { - return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); - } - - /// Returns the location of the alias name, i.e. 'foo' in - /// "namespace foo = ns::bar;". - SourceLocation getAliasLoc() const { return getLocation(); } - - /// Returns the location of the \c namespace keyword. - SourceLocation getNamespaceLoc() const { return NamespaceLoc; } - - /// Returns the location of the identifier in the named namespace. - SourceLocation getTargetNameLoc() const { return IdentLoc; } - - /// \brief Retrieve the namespace that this alias refers to, which - /// may either be a NamespaceDecl or a NamespaceAliasDecl. - NamedDecl *getAliasedNamespace() const { return Namespace; } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(NamespaceLoc, IdentLoc); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == NamespaceAlias; } -}; - -/// \brief Represents a shadow declaration introduced into a scope by a -/// (resolved) using declaration. -/// -/// For example, -/// \code -/// namespace A { -/// void foo(); -/// } -/// namespace B { -/// using A::foo; // <- a UsingDecl -/// // Also creates a UsingShadowDecl for A::foo() in B -/// } -/// \endcode -class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { - void anchor() override; - - /// The referenced declaration. - NamedDecl *Underlying; - - /// \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(ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target) - : NamedDecl(UsingShadow, DC, Loc, DeclarationName()), - redeclarable_base(C), Underlying(Target), - UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) { - if (Target) { - setDeclName(Target->getDeclName()); - IdentifierNamespace = Target->getIdentifierNamespace(); - } - setImplicit(); - } - - typedef Redeclarable<UsingShadowDecl> redeclarable_base; - UsingShadowDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - UsingShadowDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - UsingShadowDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation Loc, UsingDecl *Using, - NamedDecl *Target) { - return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target); - } - - static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - - UsingShadowDecl *getCanonicalDecl() override { - return getFirstDecl(); - } - const UsingShadowDecl *getCanonicalDecl() const { - return getFirstDecl(); - } - - /// \brief Gets the underlying declaration which has been brought into the - /// local scope. - NamedDecl *getTargetDecl() const { return Underlying; } - - /// \brief Sets the underlying declaration which has been brought into the - /// local scope. - void setTargetDecl(NamedDecl* ND) { - assert(ND && "Target decl is null!"); - Underlying = ND; - IdentifierNamespace = ND->getIdentifierNamespace(); - } - - /// \brief Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const; - - /// \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 classofKind(Kind K) { return K == Decl::UsingShadow; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a C++ using-declaration. -/// -/// For example: -/// \code -/// using someNameSpace::someIdentifier; -/// \endcode -class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { - void anchor() override; - - /// \brief The source location of the 'using' keyword itself. - SourceLocation UsingLocation; - - /// \brief The nested-name-specifier that precedes the name. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief Provides source/type location info for the declaration name - /// embedded in the ValueDecl base class. - DeclarationNameLoc DNLoc; - - /// \brief The first shadow declaration of the shadow decl chain associated - /// with this using declaration. - /// - /// The bool member of the pair store whether this decl has the \c typename - /// keyword. - llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow; - - UsingDecl(DeclContext *DC, SourceLocation UL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) - : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), - UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) { - } - -public: - /// \brief Return the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } - - /// \brief Set the source location of the 'using' keyword. - void setUsingLoc(SourceLocation L) { UsingLocation = L; } - - /// \brief Retrieve the nested-name-specifier that qualifies the name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); - } - - /// \brief Return true if it is a C++03 access declaration (no 'using'). - bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - - /// \brief Return true if the using declaration has 'typename'. - bool hasTypename() const { return FirstUsingShadow.getInt(); } - - /// \brief Sets whether the using declaration has 'typename'. - void setTypename(bool TN) { FirstUsingShadow.setInt(TN); } - - /// \brief Iterates through the using shadow declarations associated 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(nullptr) { } - explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { } - - reference operator*() const { return Current; } - pointer operator->() const { return Current; } - - shadow_iterator& operator++() { - Current = Current->getNextUsingShadowDecl(); - return *this; - } - - 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; - } - }; - - typedef llvm::iterator_range<shadow_iterator> shadow_range; - - shadow_range shadows() const { - return shadow_range(shadow_begin(), shadow_end()); - } - shadow_iterator shadow_begin() const { - return shadow_iterator(FirstUsingShadow.getPointer()); - } - shadow_iterator shadow_end() const { return shadow_iterator(); } - - /// \brief Return the number of shadowed declarations associated with this - /// using declaration. - 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, - SourceLocation UsingL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, - bool HasTypenameKeyword); - - static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Retrieves the canonical declaration of this declaration. - UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } - const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Using; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a dependent using declaration which was not marked with -/// \c typename. -/// -/// Unlike non-dependent using declarations, these *only* bring through -/// non-types; otherwise they would break two-phase lookup. -/// -/// \code -/// template \<class T> class A : public Base<T> { -/// using Base<T>::foo; -/// }; -/// \endcode -class UnresolvedUsingValueDecl : public ValueDecl, - public Mergeable<UnresolvedUsingValueDecl> { - void anchor() override; - - /// \brief The source location of the 'using' keyword - SourceLocation UsingLocation; - - /// \brief The nested-name-specifier that precedes the name. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief Provides source/type location info for the declaration name - /// embedded in the ValueDecl base class. - DeclarationNameLoc DNLoc; - - UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, - SourceLocation UsingLoc, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) - : ValueDecl(UnresolvedUsingValue, DC, - NameInfo.getLoc(), NameInfo.getName(), Ty), - UsingLocation(UsingLoc), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()) - { } - -public: - /// \brief Returns the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } - - /// \brief Set the source location of the 'using' keyword. - void setUsingLoc(SourceLocation L) { UsingLocation = L; } - - /// \brief Return true if it is a C++03 access declaration (no 'using'). - bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - - /// \brief Retrieve the nested-name-specifier that qualifies the name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); - } - - static UnresolvedUsingValueDecl * - Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo); - - static UnresolvedUsingValueDecl * - CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Retrieves the canonical declaration of this declaration. - UnresolvedUsingValueDecl *getCanonicalDecl() override { - return getFirstDecl(); - } - const UnresolvedUsingValueDecl *getCanonicalDecl() const { - return getFirstDecl(); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Represents a dependent using declaration which was marked with -/// \c typename. -/// -/// \code -/// template \<class T> class A : public Base<T> { -/// using typename Base<T>::foo; -/// }; -/// \endcode -/// -/// The type associated with an unresolved using typename decl is -/// currently always a typename type. -class UnresolvedUsingTypenameDecl - : public TypeDecl, - public Mergeable<UnresolvedUsingTypenameDecl> { - void anchor() override; - - /// \brief The source location of the 'typename' keyword - SourceLocation TypenameLocation; - - /// \brief The nested-name-specifier that precedes the name. - NestedNameSpecifierLoc QualifierLoc; - - UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TargetNameLoc, - IdentifierInfo *TargetName) - : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, - UsingLoc), - TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } - - friend class ASTDeclReader; - -public: - /// \brief Returns the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return getLocStart(); } - - /// \brief Returns the source location of the 'typename' keyword. - SourceLocation getTypenameLoc() const { return TypenameLocation; } - - /// \brief Retrieve the nested-name-specifier that qualifies the name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - static UnresolvedUsingTypenameDecl * - Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TargetNameLoc, DeclarationName TargetName); - - static UnresolvedUsingTypenameDecl * - CreateDeserialized(ASTContext &C, unsigned ID); - - /// Retrieves the canonical declaration of this declaration. - UnresolvedUsingTypenameDecl *getCanonicalDecl() override { - return getFirstDecl(); - } - const UnresolvedUsingTypenameDecl *getCanonicalDecl() const { - return getFirstDecl(); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } -}; - -/// \brief Represents a C++11 static_assert declaration. -class StaticAssertDecl : public Decl { - virtual void anchor(); - llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; - StringLiteral *Message; - SourceLocation RParenLoc; - - StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc, bool Failed) - : Decl(StaticAssert, DC, StaticAssertLoc), - AssertExprAndFailed(AssertExpr, Failed), Message(Message), - RParenLoc(RParenLoc) { } - -public: - static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc, bool Failed); - static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } - const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } - - StringLiteral *getMessage() { return Message; } - const StringLiteral *getMessage() const { return Message; } - - bool isFailed() const { return AssertExprAndFailed.getInt(); } - - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(getLocation(), getRParenLoc()); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == StaticAssert; } - - friend class ASTDeclReader; -}; - -/// An instance of this class represents the declaration of a property -/// member. This is a Microsoft extension to C++, first introduced in -/// Visual Studio .NET 2003 as a parallel to similar features in C# -/// and Managed C++. -/// -/// A property must always be a non-static class member. -/// -/// A property member superficially resembles a non-static data -/// member, except preceded by a property attribute: -/// __declspec(property(get=GetX, put=PutX)) int x; -/// Either (but not both) of the 'get' and 'put' names may be omitted. -/// -/// A reference to a property is always an lvalue. If the lvalue -/// undergoes lvalue-to-rvalue conversion, then a getter name is -/// required, and that member is called with no arguments. -/// If the lvalue is assigned into, then a setter name is required, -/// and that member is called with one argument, the value assigned. -/// Both operations are potentially overloaded. Compound assignments -/// are permitted, as are the increment and decrement operators. -/// -/// The getter and putter methods are permitted to be overloaded, -/// although their return and parameter types are subject to certain -/// restrictions according to the type of the property. -/// -/// A property declared using an incomplete array type may -/// additionally be subscripted, adding extra parameters to the getter -/// and putter methods. -class MSPropertyDecl : public DeclaratorDecl { - IdentifierInfo *GetterId, *SetterId; - - MSPropertyDecl(DeclContext *DC, SourceLocation L, DeclarationName N, - QualType T, TypeSourceInfo *TInfo, SourceLocation StartL, - IdentifierInfo *Getter, IdentifierInfo *Setter) - : DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), - GetterId(Getter), SetterId(Setter) {} - -public: - static MSPropertyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, DeclarationName N, QualType T, - TypeSourceInfo *TInfo, SourceLocation StartL, - IdentifierInfo *Getter, IdentifierInfo *Setter); - static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - static bool classof(const Decl *D) { return D->getKind() == MSProperty; } - - bool hasGetter() const { return GetterId != nullptr; } - IdentifierInfo* getGetterId() const { return GetterId; } - bool hasSetter() const { return SetterId != nullptr; } - IdentifierInfo* getSetterId() const { return SetterId; } - - friend class ASTDeclReader; -}; - -/// Insertion operator for diagnostics. This allows sending an AccessSpecifier -/// into a diagnostic with <<. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - AccessSpecifier AS); - -const PartialDiagnostic &operator<<(const PartialDiagnostic &DB, - AccessSpecifier AS); - -} // end namespace clang - -#endif diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h deleted file mode 100644 index ff37758..0000000 --- a/include/clang/AST/DeclContextInternals.h +++ /dev/null @@ -1,264 +0,0 @@ -//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the data structures used in the implementation -// of DeclContext. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H -#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H - -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclarationName.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallVector.h" -#include <algorithm> - -namespace clang { - -class DependentDiagnostic; - -/// \brief An array of decls optimized for the common case of only containing -/// one entry. -struct StoredDeclsList { - - /// \brief When in vector form, this is what the Data pointer points to. - typedef SmallVector<NamedDecl *, 4> DeclsTy; - - /// \brief A collection of declarations, with a flag to indicate if we have - /// further external declarations. - typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy; - - /// \brief The stored data, which will be either a pointer to a NamedDecl, - /// or a pointer to a vector with a flag to indicate if there are further - /// external declarations. - llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data; - -public: - StoredDeclsList() {} - - StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { - RHS.Data = (NamedDecl *)nullptr; - } - - ~StoredDeclsList() { - // If this is a vector-form, free the vector. - if (DeclsTy *Vector = getAsVector()) - delete Vector; - } - - StoredDeclsList &operator=(StoredDeclsList &&RHS) { - if (DeclsTy *Vector = getAsVector()) - delete Vector; - Data = RHS.Data; - RHS.Data = (NamedDecl *)nullptr; - return *this; - } - - bool isNull() const { return Data.isNull(); } - - NamedDecl *getAsDecl() const { - return Data.dyn_cast<NamedDecl *>(); - } - - DeclsAndHasExternalTy getAsVectorAndHasExternal() const { - return Data.dyn_cast<DeclsAndHasExternalTy>(); - } - - DeclsTy *getAsVector() const { - return getAsVectorAndHasExternal().getPointer(); - } - - bool hasExternalDecls() const { - return getAsVectorAndHasExternal().getInt(); - } - - void setHasExternalDecls() { - if (DeclsTy *Vec = getAsVector()) - Data = DeclsAndHasExternalTy(Vec, true); - else { - DeclsTy *VT = new DeclsTy(); - if (NamedDecl *OldD = getAsDecl()) - VT->push_back(OldD); - Data = DeclsAndHasExternalTy(VT, true); - } - } - - void setOnlyValue(NamedDecl *ND) { - assert(!getAsVector() && "Not inline"); - Data = ND; - // Make sure that Data is a plain NamedDecl* so we can use its address - // at getLookupResult. - assert(*(NamedDecl **)&Data == ND && - "PointerUnion mangles the NamedDecl pointer!"); - } - - void remove(NamedDecl *D) { - assert(!isNull() && "removing from empty list"); - if (NamedDecl *Singleton = getAsDecl()) { - assert(Singleton == D && "list is different singleton"); - (void)Singleton; - Data = (NamedDecl *)nullptr; - return; - } - - DeclsTy &Vec = *getAsVector(); - DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); - assert(I != Vec.end() && "list does not contain decl"); - Vec.erase(I); - - assert(std::find(Vec.begin(), Vec.end(), D) - == Vec.end() && "list still contains decl"); - } - - /// \brief Remove any declarations which were imported from an external - /// AST source. - void removeExternalDecls() { - if (isNull()) { - // Nothing to do. - } else if (NamedDecl *Singleton = getAsDecl()) { - if (Singleton->isFromASTFile()) - *this = StoredDeclsList(); - } else { - DeclsTy &Vec = *getAsVector(); - Vec.erase(std::remove_if(Vec.begin(), Vec.end(), - std::mem_fun(&Decl::isFromASTFile)), - Vec.end()); - // Don't have any external decls any more. - Data = DeclsAndHasExternalTy(&Vec, false); - } - } - - /// getLookupResult - Return an array of all the decls that this list - /// represents. - DeclContext::lookup_result getLookupResult() { - if (isNull()) - return DeclContext::lookup_result(); - - // If we have a single NamedDecl, return it. - if (NamedDecl *ND = getAsDecl()) { - assert(!isNull() && "Empty list isn't allowed"); - - // Data is a raw pointer to a NamedDecl*, return it. - return DeclContext::lookup_result(ND); - } - - assert(getAsVector() && "Must have a vector at this point"); - DeclsTy &Vector = *getAsVector(); - - // Otherwise, we have a range result. - return DeclContext::lookup_result(Vector); - } - - /// HandleRedeclaration - If this is a redeclaration of an existing decl, - /// replace the old one with D and return true. Otherwise return false. - bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) { - // Most decls only have one entry in their list, special case it. - if (NamedDecl *OldD = getAsDecl()) { - if (!D->declarationReplaces(OldD, IsKnownNewer)) - return false; - setOnlyValue(D); - return true; - } - - // Determine if this declaration is actually a redeclaration. - DeclsTy &Vec = *getAsVector(); - for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); - OD != ODEnd; ++OD) { - NamedDecl *OldD = *OD; - if (D->declarationReplaces(OldD, IsKnownNewer)) { - *OD = D; - return true; - } - } - - return false; - } - - /// AddSubsequentDecl - This is called on the second and later decl when it is - /// not a redeclaration to merge it into the appropriate place in our list. - /// - void AddSubsequentDecl(NamedDecl *D) { - assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); - - // If this is the second decl added to the list, convert this to vector - // form. - if (NamedDecl *OldD = getAsDecl()) { - DeclsTy *VT = new DeclsTy(); - VT->push_back(OldD); - Data = DeclsAndHasExternalTy(VT, false); - } - - DeclsTy &Vec = *getAsVector(); - - // Using directives end up in a special entry which contains only - // other using directives, so all this logic is wasted for them. - // But avoiding the logic wastes time in the far-more-common case - // that we're *not* adding a new using directive. - - // Tag declarations always go at the end of the list so that an - // iterator which points at the first tag will start a span of - // decls that only contains tags. - if (D->hasTagIdentifierNamespace()) - Vec.push_back(D); - - // Resolved using declarations go at the front of the list so that - // they won't show up in other lookup results. Unresolved using - // declarations (which are always in IDNS_Using | IDNS_Ordinary) - // follow that so that the using declarations will be contiguous. - else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { - DeclsTy::iterator I = Vec.begin(); - if (D->getIdentifierNamespace() != Decl::IDNS_Using) { - while (I != Vec.end() && - (*I)->getIdentifierNamespace() == Decl::IDNS_Using) - ++I; - } - Vec.insert(I, D); - - // All other declarations go at the end of the list, but before any - // tag declarations. But we can be clever about tag declarations - // because there can only ever be one in a scope. - } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { - NamedDecl *TagD = Vec.back(); - Vec.back() = D; - Vec.push_back(TagD); - } else - Vec.push_back(D); - } -}; - -class StoredDeclsMap - : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { - -public: - static void DestroyAll(StoredDeclsMap *Map, bool Dependent); - -private: - friend class ASTContext; // walks the chain deleting these - friend class DeclContext; - llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; -}; - -class DependentStoredDeclsMap : public StoredDeclsMap { -public: - DependentStoredDeclsMap() : FirstDiagnostic(nullptr) {} - -private: - friend class DependentDiagnostic; - friend class DeclContext; // iterates over diagnostics - - DependentDiagnostic *FirstDiagnostic; -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h deleted file mode 100644 index 27b0388..0000000 --- a/include/clang/AST/DeclFriend.h +++ /dev/null @@ -1,243 +0,0 @@ -//===-- DeclFriend.h - Classes for C++ friend declarations -*- 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 section of the AST representing C++ friend -// declarations. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLFRIEND_H -#define LLVM_CLANG_AST_DECLFRIEND_H - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/TypeLoc.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -/// FriendDecl - Represents the declaration of a friend entity, -/// which can be a function, a type, or a templated function or type. -// For example: -/// -/// @code -/// template <typename T> class A { -/// friend int foo(T); -/// friend class B; -/// friend T; // only in C++0x -/// template <typename U> friend class C; -/// template <typename U> friend A& operator+=(A&, const U&) { ... } -/// }; -/// @endcode -/// -/// The semantic context of a friend decl is its declaring class. -class FriendDecl final - : public Decl, - private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> { - virtual void anchor(); -public: - typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; - -private: - // The declaration that's a friend of this class. - FriendUnion Friend; - - // A pointer to the next friend in the sequence. - 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 : 1; - - // The number of "outer" template parameter lists in non-templatic - // (currently unsupported) friend type declarations, such as - // template <class T> friend class A<T>::B; - unsigned NumTPLists : 31; - - friend class CXXRecordDecl::friend_iterator; - friend class CXXRecordDecl; - - FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, - SourceLocation FriendL, - ArrayRef<TemplateParameterList*> FriendTypeTPLists) - : Decl(Decl::Friend, DC, L), - Friend(Friend), - NextFriend(), - FriendLoc(FriendL), - UnsupportedFriend(false), - NumTPLists(FriendTypeTPLists.size()) { - for (unsigned i = 0; i < NumTPLists; ++i) - getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i]; - } - - FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) - : Decl(Decl::Friend, Empty), NextFriend(), - NumTPLists(NumFriendTypeTPLists) { } - - FriendDecl *getNextFriend() { - if (!NextFriend.isOffset()) - return cast_or_null<FriendDecl>(NextFriend.get(nullptr)); - return getNextFriendSlowCase(); - } - FriendDecl *getNextFriendSlowCase(); - -public: - static FriendDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, FriendUnion Friend_, - SourceLocation FriendL, - ArrayRef<TemplateParameterList*> FriendTypeTPLists - = None); - static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, - unsigned FriendTypeNumTPLists); - - /// If this friend declaration names an (untemplated but possibly - /// dependent) type, return the type; otherwise return null. This - /// is used for elaborated-type-specifiers and, in C++0x, for - /// arbitrary friend type declarations. - TypeSourceInfo *getFriendType() const { - return Friend.dyn_cast<TypeSourceInfo*>(); - } - unsigned getFriendTypeNumTemplateParameterLists() const { - return NumTPLists; - } - TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { - assert(N < NumTPLists); - return getTrailingObjects<TemplateParameterList *>()[N]; - } - - /// If this friend declaration doesn't name a type, return the inner - /// declaration. - NamedDecl *getFriendDecl() const { - return Friend.dyn_cast<NamedDecl*>(); - } - - /// Retrieves the location of the 'friend' keyword. - SourceLocation getFriendLoc() const { - return FriendLoc; - } - - /// Retrieves the source range for the friend declaration. - SourceRange getSourceRange() const override LLVM_READONLY { - if (NamedDecl *ND = getFriendDecl()) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) - return FD->getSourceRange(); - if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) - return FTD->getSourceRange(); - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) - return CTD->getSourceRange(); - if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) { - if (DD->getOuterLocStart() != DD->getInnerLocStart()) - return DD->getSourceRange(); - } - return SourceRange(getFriendLoc(), ND->getLocEnd()); - } - else if (TypeSourceInfo *TInfo = getFriendType()) { - SourceLocation StartL = - (NumTPLists == 0) ? getFriendLoc() - : getTrailingObjects<TemplateParameterList *>()[0] - ->getTemplateLoc(); - return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); - } - else - return SourceRange(getFriendLoc(), getLocation()); - } - - /// 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 classofKind(Kind K) { return K == Decl::Friend; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; -}; - -/// An iterator over the friend declarations of a class. -class CXXRecordDecl::friend_iterator { - FriendDecl *Ptr; - - friend class CXXRecordDecl; - explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {} -public: - friend_iterator() {} - - typedef FriendDecl *value_type; - typedef FriendDecl *reference; - typedef FriendDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; - - reference operator*() const { return Ptr; } - - friend_iterator &operator++() { - assert(Ptr && "attempt to increment past end of friend list"); - Ptr = Ptr->getNextFriend(); - return *this; - } - - friend_iterator operator++(int) { - friend_iterator tmp = *this; - ++*this; - return tmp; - } - - bool operator==(const friend_iterator &Other) const { - return Ptr == Other.Ptr; - } - - bool operator!=(const friend_iterator &Other) const { - return Ptr != Other.Ptr; - } - - friend_iterator &operator+=(difference_type N) { - assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator"); - while (N--) - ++*this; - return *this; - } - - friend_iterator operator+(difference_type N) const { - friend_iterator tmp = *this; - tmp += N; - return tmp; - } -}; - -inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { - return friend_iterator(getFirstFriend()); -} - -inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { - return friend_iterator(nullptr); -} - -inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const { - return friend_range(friend_begin(), friend_end()); -} - -inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { - assert(!FD->NextFriend && "friend already has next friend?"); - FD->NextFriend = data().FirstFriend; - data().FirstFriend = FD; -} - -} - -#endif diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h deleted file mode 100644 index c84bb5e..0000000 --- a/include/clang/AST/DeclGroup.h +++ /dev/null @@ -1,154 +0,0 @@ -//===--- DeclGroup.h - Classes for representing groups of Decls -*- 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 DeclGroup, DeclGroupRef, and OwningDeclGroup classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLGROUP_H -#define LLVM_CLANG_AST_DECLGROUP_H - -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/TrailingObjects.h" -#include <cassert> - -namespace clang { - -class ASTContext; -class Decl; -class DeclGroup; -class DeclGroupIterator; - -class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { - // FIXME: Include a TypeSpecifier object. - unsigned NumDecls; - -private: - DeclGroup() : NumDecls(0) {} - DeclGroup(unsigned numdecls, Decl** decls); - -public: - static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); - - unsigned size() const { return NumDecls; } - - Decl*& operator[](unsigned i) { - assert (i < NumDecls && "Out-of-bounds access."); - return getTrailingObjects<Decl *>()[i]; - } - - Decl* const& operator[](unsigned i) const { - assert (i < NumDecls && "Out-of-bounds access."); - return getTrailingObjects<Decl *>()[i]; - } - - friend TrailingObjects; -}; - -class DeclGroupRef { - // Note this is not a PointerIntPair because we need the address of the - // non-group case to be valid as a Decl** for iteration. - enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; - Decl* D; - - Kind getKind() const { - return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); - } - -public: - DeclGroupRef() : D(nullptr) {} - - explicit DeclGroupRef(Decl* d) : D(d) {} - explicit DeclGroupRef(DeclGroup* dg) - : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} - - static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { - if (NumDecls == 0) - return DeclGroupRef(); - if (NumDecls == 1) - return DeclGroupRef(Decls[0]); - return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); - } - - typedef Decl** iterator; - typedef Decl* const * const_iterator; - - bool isNull() const { return D == nullptr; } - bool isSingleDecl() const { return getKind() == SingleDeclKind; } - bool isDeclGroup() const { return getKind() == DeclGroupKind; } - - Decl *getSingleDecl() { - assert(isSingleDecl() && "Isn't a declgroup"); - return D; - } - const Decl *getSingleDecl() const { - return const_cast<DeclGroupRef*>(this)->getSingleDecl(); - } - - DeclGroup &getDeclGroup() { - assert(isDeclGroup() && "Isn't a declgroup"); - return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); - } - const DeclGroup &getDeclGroup() const { - return const_cast<DeclGroupRef*>(this)->getDeclGroup(); - } - - iterator begin() { - if (isSingleDecl()) - return D ? &D : nullptr; - return &getDeclGroup()[0]; - } - - iterator end() { - if (isSingleDecl()) - return D ? &D+1 : nullptr; - DeclGroup &G = getDeclGroup(); - return &G[0] + G.size(); - } - - const_iterator begin() const { - if (isSingleDecl()) - return D ? &D : nullptr; - return &getDeclGroup()[0]; - } - - const_iterator end() const { - if (isSingleDecl()) - return D ? &D+1 : nullptr; - const DeclGroup &G = getDeclGroup(); - return &G[0] + G.size(); - } - - void *getAsOpaquePtr() const { return D; } - static DeclGroupRef getFromOpaquePtr(void *Ptr) { - DeclGroupRef X; - X.D = static_cast<Decl*>(Ptr); - return X; - } -}; - -} // end clang namespace - -namespace llvm { - // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. - template <typename T> - class PointerLikeTypeTraits; - template <> - class PointerLikeTypeTraits<clang::DeclGroupRef> { - public: - static inline void *getAsVoidPointer(clang::DeclGroupRef P) { - return P.getAsOpaquePtr(); - } - static inline clang::DeclGroupRef getFromVoidPointer(void *P) { - return clang::DeclGroupRef::getFromOpaquePtr(P); - } - enum { NumLowBitsAvailable = 0 }; - }; -} -#endif diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h deleted file mode 100644 index eba2266..0000000 --- a/include/clang/AST/DeclLookups.h +++ /dev/null @@ -1,115 +0,0 @@ -//===-- DeclLookups.h - Low-level interface to all names in a DC-*- 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 DeclContext::all_lookups_iterator. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLLOOKUPS_H -#define LLVM_CLANG_AST_DECLLOOKUPS_H - -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/DeclarationName.h" - -namespace clang { - -/// all_lookups_iterator - An iterator that provides a view over the results -/// of looking up every possible name. -class DeclContext::all_lookups_iterator { - StoredDeclsMap::iterator It, End; -public: - typedef lookup_result value_type; - typedef lookup_result reference; - typedef lookup_result pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - all_lookups_iterator() {} - all_lookups_iterator(StoredDeclsMap::iterator It, - StoredDeclsMap::iterator End) - : It(It), End(End) {} - - DeclarationName getLookupName() const { return It->first; } - - reference operator*() const { return It->second.getLookupResult(); } - pointer operator->() const { return It->second.getLookupResult(); } - - all_lookups_iterator& operator++() { - // Filter out using directives. They don't belong as results from name - // lookup anyways, except as an implementation detail. Users of the API - // should not expect to get them (or worse, rely on it). - do { - ++It; - } while (It != End && - It->first == DeclarationName::getUsingDirectiveName()); - - return *this; - } - - all_lookups_iterator operator++(int) { - all_lookups_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) { - return x.It == y.It; - } - friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) { - return x.It != y.It; - } -}; - -inline DeclContext::lookups_range DeclContext::lookups() const { - DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (Primary->hasExternalVisibleStorage()) - getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); - if (StoredDeclsMap *Map = Primary->buildLookup()) - return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), - all_lookups_iterator(Map->end(), Map->end())); - - // Synthesize an empty range. This requires that two default constructed - // versions of these iterators form a valid empty range. - return lookups_range(all_lookups_iterator(), all_lookups_iterator()); -} - -inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { - return lookups().begin(); -} - -inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const { - return lookups().end(); -} - -inline DeclContext::lookups_range DeclContext::noload_lookups() const { - DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (StoredDeclsMap *Map = Primary->getLookupPtr()) - return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), - all_lookups_iterator(Map->end(), Map->end())); - - // Synthesize an empty range. This requires that two default constructed - // versions of these iterators form a valid empty range. - return lookups_range(all_lookups_iterator(), all_lookups_iterator()); -} - -inline -DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const { - return noload_lookups().begin(); -} - -inline -DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const { - return noload_lookups().end(); -} - -} // end namespace clang - -#endif diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h deleted file mode 100644 index f46078f..0000000 --- a/include/clang/AST/DeclObjC.h +++ /dev/null @@ -1,2742 +0,0 @@ -//===--- DeclObjC.h - Classes for representing declarations -----*- 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 DeclObjC interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLOBJC_H -#define LLVM_CLANG_AST_DECLOBJC_H - -#include "clang/AST/Decl.h" -#include "clang/AST/SelectorLocationsKind.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Compiler.h" - -namespace clang { -class Expr; -class Stmt; -class FunctionDecl; -class RecordDecl; -class ObjCIvarDecl; -class ObjCMethodDecl; -class ObjCProtocolDecl; -class ObjCCategoryDecl; -class ObjCPropertyDecl; -class ObjCPropertyImplDecl; -class CXXCtorInitializer; - -class ObjCListBase { - ObjCListBase(const ObjCListBase &) = delete; - void operator=(const ObjCListBase &) = delete; -protected: - /// List is an array of pointers to objects that are not owned by this object. - void **List; - unsigned NumElts; - -public: - ObjCListBase() : List(nullptr), NumElts(0) {} - unsigned size() const { return NumElts; } - bool empty() const { return NumElts == 0; } - -protected: - void set(void *const* InList, unsigned Elts, ASTContext &Ctx); -}; - - -/// ObjCList - This is a simple template class used to hold various lists of -/// decls etc, which is heavily used by the ObjC front-end. This only use case -/// this supports is setting the list all at once and then reading elements out -/// of it. -template <typename T> -class ObjCList : public ObjCListBase { -public: - void set(T* const* InList, unsigned Elts, ASTContext &Ctx) { - ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx); - } - - typedef T* const * iterator; - iterator begin() const { return (iterator)List; } - iterator end() const { return (iterator)List+NumElts; } - - T* operator[](unsigned Idx) const { - assert(Idx < NumElts && "Invalid access"); - return (T*)List[Idx]; - } -}; - -/// \brief A list of Objective-C protocols, along with the source -/// locations at which they were referenced. -class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> { - SourceLocation *Locations; - - using ObjCList<ObjCProtocolDecl>::set; - -public: - ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(nullptr) { } - - typedef const SourceLocation *loc_iterator; - loc_iterator loc_begin() const { return Locations; } - loc_iterator loc_end() const { return Locations + size(); } - - void set(ObjCProtocolDecl* const* InList, unsigned Elts, - const SourceLocation *Locs, ASTContext &Ctx); -}; - - -/// ObjCMethodDecl - Represents an instance or class method declaration. -/// ObjC methods can be declared within 4 contexts: class interfaces, -/// categories, protocols, and class implementations. While C++ member -/// functions leverage C syntax, Objective-C method syntax is modeled after -/// Smalltalk (using colons to specify argument types/expressions). -/// Here are some brief examples: -/// -/// Setter/getter instance methods: -/// - (void)setMenu:(NSMenu *)menu; -/// - (NSMenu *)menu; -/// -/// Instance method that takes 2 NSView arguments: -/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView; -/// -/// Getter class method: -/// + (NSMenu *)defaultMenu; -/// -/// A selector represents a unique name for a method. The selector names for -/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu. -/// -class ObjCMethodDecl : public NamedDecl, public DeclContext { -public: - enum ImplementationControl { None, Required, Optional }; -private: - // The conventional meaning of this method; an ObjCMethodFamily. - // This is not serialized; instead, it is computed on demand and - // cached. - mutable unsigned Family : ObjCMethodFamilyBitWidth; - - /// instance (true) or class (false) method. - unsigned IsInstance : 1; - unsigned IsVariadic : 1; - - /// True if this method is the getter or setter for an explicit property. - unsigned IsPropertyAccessor : 1; - - // Method has a definition. - unsigned IsDefined : 1; - - /// \brief Method redeclaration in the same interface. - unsigned IsRedeclaration : 1; - - /// \brief Is redeclared in the same interface. - mutable unsigned HasRedeclaration : 1; - - // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum - /// \@required/\@optional - unsigned DeclImplementation : 2; - - // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum - /// in, inout, etc. - unsigned objcDeclQualifier : 7; - - /// \brief Indicates whether this method has a related result type. - unsigned RelatedResultType : 1; - - /// \brief Whether the locations of the selector identifiers are in a - /// "standard" position, a enum SelectorLocationsKind. - unsigned SelLocsKind : 2; - - /// \brief Whether this method overrides any other in the class hierarchy. - /// - /// A method is said to override any method in the class's - /// base classes, its protocols, or its categories' protocols, that has - /// the same selector and is of the same kind (class or instance). - /// A method in an implementation is not considered as overriding the same - /// method in the interface or its categories. - unsigned IsOverriding : 1; - - /// \brief Indicates if the method was a definition but its body was skipped. - unsigned HasSkippedBody : 1; - - // Return type of this method. - QualType MethodDeclType; - - // Type source information for the return type. - TypeSourceInfo *ReturnTInfo; - - /// \brief Array of ParmVarDecls for the formal parameters of this method - /// and optionally followed by selector locations. - void *ParamsAndSelLocs; - unsigned NumParams; - - /// List of attributes for this method declaration. - SourceLocation DeclEndLoc; // the location of the ';' or '{'. - - // The following are only used for method definitions, null otherwise. - LazyDeclStmtPtr Body; - - /// SelfDecl - Decl for the implicit self parameter. This is lazily - /// constructed by createImplicitParams. - ImplicitParamDecl *SelfDecl; - /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily - /// constructed by createImplicitParams. - ImplicitParamDecl *CmdDecl; - - SelectorLocationsKind getSelLocsKind() const { - return (SelectorLocationsKind)SelLocsKind; - } - bool hasStandardSelLocs() const { - return getSelLocsKind() != SelLoc_NonStandard; - } - - /// \brief Get a pointer to the stored selector identifiers locations array. - /// No locations will be stored if HasStandardSelLocs is true. - SourceLocation *getStoredSelLocs() { - return reinterpret_cast<SourceLocation*>(getParams() + NumParams); - } - const SourceLocation *getStoredSelLocs() const { - return reinterpret_cast<const SourceLocation*>(getParams() + NumParams); - } - - /// \brief Get a pointer to the stored selector identifiers locations array. - /// No locations will be stored if HasStandardSelLocs is true. - ParmVarDecl **getParams() { - return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs); - } - const ParmVarDecl *const *getParams() const { - return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs); - } - - /// \brief Get the number of stored selector identifiers locations. - /// No locations will be stored if HasStandardSelLocs is true. - unsigned getNumStoredSelLocs() const { - if (hasStandardSelLocs()) - return 0; - return getNumSelectorLocs(); - } - - void setParamsAndSelLocs(ASTContext &C, - ArrayRef<ParmVarDecl*> Params, - ArrayRef<SourceLocation> SelLocs); - - ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, - DeclContext *contextDecl, bool isInstance = true, - bool isVariadic = false, bool isPropertyAccessor = false, - bool isImplicitlyDeclared = false, bool isDefined = false, - ImplementationControl impControl = None, - bool HasRelatedResultType = false) - : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), - IsInstance(isInstance), IsVariadic(isVariadic), - IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined), - IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), - objcDeclQualifier(OBJC_TQ_None), - RelatedResultType(HasRelatedResultType), - SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), - MethodDeclType(T), ReturnTInfo(ReturnTInfo), ParamsAndSelLocs(nullptr), - NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(nullptr), - CmdDecl(nullptr) { - setImplicit(isImplicitlyDeclared); - } - - /// \brief A definition will return its interface declaration. - /// An interface declaration will return its definition. - /// Otherwise it will return itself. - ObjCMethodDecl *getNextRedeclarationImpl() override; - -public: - static ObjCMethodDecl * - Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, - DeclContext *contextDecl, bool isInstance = true, - bool isVariadic = false, bool isPropertyAccessor = false, - bool isImplicitlyDeclared = false, bool isDefined = false, - ImplementationControl impControl = None, - bool HasRelatedResultType = false); - - static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - ObjCMethodDecl *getCanonicalDecl() override; - const ObjCMethodDecl *getCanonicalDecl() const { - return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl(); - } - - ObjCDeclQualifier getObjCDeclQualifier() const { - return ObjCDeclQualifier(objcDeclQualifier); - } - void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } - - /// \brief Determine whether this method has a result type that is related - /// to the message receiver's type. - bool hasRelatedResultType() const { return RelatedResultType; } - - /// \brief Note whether this method has a related result type. - void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; } - - /// \brief True if this is a method redeclaration in the same interface. - bool isRedeclaration() const { return IsRedeclaration; } - void setAsRedeclaration(const ObjCMethodDecl *PrevMethod); - - /// \brief Returns the location where the declarator ends. It will be - /// the location of ';' for a method declaration and the location of '{' - /// for a method definition. - SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; } - - // Location information, modeled after the Stmt API. - SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY; - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(getLocation(), getLocEnd()); - } - - SourceLocation getSelectorStartLoc() const { - if (isImplicit()) - return getLocStart(); - return getSelectorLoc(0); - } - SourceLocation getSelectorLoc(unsigned Index) const { - assert(Index < getNumSelectorLocs() && "Index out of range!"); - if (hasStandardSelLocs()) - return getStandardSelectorLoc(Index, getSelector(), - getSelLocsKind() == SelLoc_StandardWithSpace, - parameters(), - DeclEndLoc); - return getStoredSelLocs()[Index]; - } - - void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const; - - unsigned getNumSelectorLocs() const { - if (isImplicit()) - return 0; - Selector Sel = getSelector(); - if (Sel.isUnarySelector()) - return 1; - return Sel.getNumArgs(); - } - - ObjCInterfaceDecl *getClassInterface(); - const ObjCInterfaceDecl *getClassInterface() const { - return const_cast<ObjCMethodDecl*>(this)->getClassInterface(); - } - - Selector getSelector() const { return getDeclName().getObjCSelector(); } - - QualType getReturnType() const { return MethodDeclType; } - void setReturnType(QualType T) { MethodDeclType = T; } - SourceRange getReturnTypeSourceRange() const; - - /// \brief Determine the type of an expression that sends a message to this - /// function. This replaces the type parameters with the types they would - /// get if the receiver was parameterless (e.g. it may replace the type - /// parameter with 'id'). - QualType getSendResultType() const; - - /// Determine the type of an expression that sends a message to this - /// function with the given receiver type. - QualType getSendResultType(QualType receiverType) const; - - TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; } - void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; } - - // Iterator access to formal parameters. - unsigned param_size() const { return NumParams; } - typedef const ParmVarDecl *const *param_const_iterator; - typedef ParmVarDecl *const *param_iterator; - typedef llvm::iterator_range<param_iterator> param_range; - typedef llvm::iterator_range<param_const_iterator> param_const_range; - - param_range params() { return param_range(param_begin(), param_end()); } - param_const_range params() const { - return param_const_range(param_begin(), param_end()); - } - - param_const_iterator param_begin() const { - return param_const_iterator(getParams()); - } - param_const_iterator param_end() const { - return param_const_iterator(getParams() + NumParams); - } - param_iterator param_begin() { return param_iterator(getParams()); } - param_iterator param_end() { return param_iterator(getParams() + NumParams); } - - // This method returns and of the parameters which are part of the selector - // name mangling requirements. - param_const_iterator sel_param_end() const { - return param_begin() + getSelector().getNumArgs(); - } - - // ArrayRef access to formal parameters. This should eventually - // replace the iterator interface above. - ArrayRef<ParmVarDecl*> parameters() const { - return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()), - NumParams); - } - - /// \brief Sets the method's parameters and selector source locations. - /// If the method is implicit (not coming from source) \p SelLocs is - /// ignored. - void setMethodParams(ASTContext &C, - ArrayRef<ParmVarDecl*> Params, - ArrayRef<SourceLocation> SelLocs = llvm::None); - - // Iterator access to parameter types. - typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; - typedef llvm::mapped_iterator<param_const_iterator, deref_fun> - param_type_iterator; - - param_type_iterator param_type_begin() const { - return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType)); - } - param_type_iterator param_type_end() const { - return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType)); - } - - /// createImplicitParams - Used to lazily create the self and cmd - /// implict parameters. This must be called prior to using getSelfDecl() - /// or getCmdDecl(). The call is ignored if the implicit paramters - /// have already been created. - void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID); - - /// \return the type for \c self and set \arg selfIsPseudoStrong and - /// \arg selfIsConsumed accordingly. - QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID, - bool &selfIsPseudoStrong, bool &selfIsConsumed); - - ImplicitParamDecl * getSelfDecl() const { return SelfDecl; } - void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; } - ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } - void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } - - /// Determines the family of this method. - ObjCMethodFamily getMethodFamily() const; - - bool isInstanceMethod() const { return IsInstance; } - void setInstanceMethod(bool isInst) { IsInstance = isInst; } - bool isVariadic() const { return IsVariadic; } - void setVariadic(bool isVar) { IsVariadic = isVar; } - - bool isClassMethod() const { return !IsInstance; } - - bool isPropertyAccessor() const { return IsPropertyAccessor; } - void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; } - - bool isDefined() const { return IsDefined; } - void setDefined(bool isDefined) { IsDefined = isDefined; } - - /// \brief Whether this method overrides any other in the class hierarchy. - /// - /// A method is said to override any method in the class's - /// base classes, its protocols, or its categories' protocols, that has - /// the same selector and is of the same kind (class or instance). - /// A method in an implementation is not considered as overriding the same - /// method in the interface or its categories. - bool isOverriding() const { return IsOverriding; } - void setOverriding(bool isOverriding) { IsOverriding = isOverriding; } - - /// \brief Return overridden methods for the given \p Method. - /// - /// An ObjC method is considered to override any method in the class's - /// base classes (and base's categories), its protocols, or its categories' - /// protocols, that has - /// the same selector and is of the same kind (class or instance). - /// A method in an implementation is not considered as overriding the same - /// method in the interface or its categories. - void getOverriddenMethods( - SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const; - - /// \brief True if the method was a definition but its body was skipped. - bool hasSkippedBody() const { return HasSkippedBody; } - void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } - - /// \brief Returns the property associated with this method's selector. - /// - /// Note that even if this particular method is not marked as a property - /// accessor, it is still possible for it to match a property declared in a - /// superclass. Pass \c false if you only want to check the current class. - const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const; - - // Related to protocols declared in \@protocol - void setDeclImplementation(ImplementationControl ic) { - DeclImplementation = ic; - } - ImplementationControl getImplementationControl() const { - return ImplementationControl(DeclImplementation); - } - - /// Returns true if this specific method declaration is marked with the - /// designated initializer attribute. - bool isThisDeclarationADesignatedInitializer() const; - - /// Returns true if the method selector resolves to a designated initializer - /// in the class's interface. - /// - /// \param InitMethod if non-null and the function returns true, it receives - /// the method declaration that was marked with the designated initializer - /// attribute. - bool isDesignatedInitializerForTheInterface( - const ObjCMethodDecl **InitMethod = nullptr) const; - - /// \brief Determine whether this method has a body. - bool hasBody() const override { return Body.isValid(); } - - /// \brief Retrieve the body of this method, if it has one. - Stmt *getBody() const override; - - void setLazyBody(uint64_t Offset) { Body = Offset; } - - CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); } - void setBody(Stmt *B) { Body = B; } - - /// \brief Returns whether this specific method is a definition. - bool isThisDeclarationADefinition() const { return hasBody(); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCMethod; } - static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { - return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D)); - } - static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC)); - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// Describes the variance of a given generic parameter. -enum class ObjCTypeParamVariance : uint8_t { - /// The parameter is invariant: must match exactly. - Invariant, - /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when - /// the type parameter is covariant and T is a subtype of U. - Covariant, - /// The parameter is contravariant, e.g., X<T> is a subtype of X<U> - /// when the type parameter is covariant and U is a subtype of T. - Contravariant, -}; - -/// Represents the declaration of an Objective-C type parameter. -/// -/// \code -/// @interface NSDictionary<Key : id<NSCopying>, Value> -/// @end -/// \endcode -/// -/// In the example above, both \c Key and \c Value are represented by -/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>, -/// while \c Value gets an implicit bound of \c id. -/// -/// Objective-C type parameters are typedef-names in the grammar, -class ObjCTypeParamDecl : public TypedefNameDecl { - void anchor() override; - - /// Index of this type parameter in the type parameter list. - unsigned Index : 14; - - /// The variance of the type parameter. - unsigned Variance : 2; - - /// The location of the variance, if any. - SourceLocation VarianceLoc; - - /// The location of the ':', which will be valid when the bound was - /// explicitly specified. - SourceLocation ColonLoc; - - ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc, - ObjCTypeParamVariance variance, SourceLocation varianceLoc, - unsigned index, - SourceLocation nameLoc, IdentifierInfo *name, - SourceLocation colonLoc, TypeSourceInfo *boundInfo) - : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name, - boundInfo), - Index(index), Variance(static_cast<unsigned>(variance)), - VarianceLoc(varianceLoc), ColonLoc(colonLoc) { } - -public: - static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc, - ObjCTypeParamVariance variance, - SourceLocation varianceLoc, - unsigned index, - SourceLocation nameLoc, - IdentifierInfo *name, - SourceLocation colonLoc, - TypeSourceInfo *boundInfo); - static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Determine the variance of this type parameter. - ObjCTypeParamVariance getVariance() const { - return static_cast<ObjCTypeParamVariance>(Variance); - } - - /// Set the variance of this type parameter. - void setVariance(ObjCTypeParamVariance variance) { - Variance = static_cast<unsigned>(variance); - } - - /// Retrieve the location of the variance keyword. - SourceLocation getVarianceLoc() const { return VarianceLoc; } - - /// Retrieve the index into its type parameter list. - unsigned getIndex() const { return Index; } - - /// Whether this type parameter has an explicitly-written type bound, e.g., - /// "T : NSView". - bool hasExplicitBound() const { return ColonLoc.isValid(); } - - /// Retrieve the location of the ':' separating the type parameter name - /// from the explicitly-specified bound. - SourceLocation getColonLoc() const { return ColonLoc; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCTypeParam; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// Stores a list of Objective-C type parameters for a parameterized class -/// or a category/extension thereof. -/// -/// \code -/// @interface NSArray<T> // stores the <T> -/// @end -/// \endcode -class ObjCTypeParamList final - : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> { - /// Stores the components of a SourceRange as a POD. - struct PODSourceRange { - unsigned Begin; - unsigned End; - }; - - union { - /// Location of the left and right angle brackets. - PODSourceRange Brackets; - - // Used only for alignment. - ObjCTypeParamDecl *AlignmentHack; - }; - - /// The number of parameters in the list, which are tail-allocated. - unsigned NumParams; - - ObjCTypeParamList(SourceLocation lAngleLoc, - ArrayRef<ObjCTypeParamDecl *> typeParams, - SourceLocation rAngleLoc); - -public: - /// Create a new Objective-C type parameter list. - static ObjCTypeParamList *create(ASTContext &ctx, - SourceLocation lAngleLoc, - ArrayRef<ObjCTypeParamDecl *> typeParams, - SourceLocation rAngleLoc); - - /// Iterate through the type parameters in the list. - typedef ObjCTypeParamDecl **iterator; - - iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); } - - iterator end() { return begin() + size(); } - - /// Determine the number of type parameters in this list. - unsigned size() const { return NumParams; } - - // Iterate through the type parameters in the list. - typedef ObjCTypeParamDecl * const *const_iterator; - - const_iterator begin() const { - return getTrailingObjects<ObjCTypeParamDecl *>(); - } - - const_iterator end() const { - return begin() + size(); - } - - ObjCTypeParamDecl *front() const { - assert(size() > 0 && "empty Objective-C type parameter list"); - return *begin(); - } - - ObjCTypeParamDecl *back() const { - assert(size() > 0 && "empty Objective-C type parameter list"); - return *(end() - 1); - } - - SourceLocation getLAngleLoc() const { - return SourceLocation::getFromRawEncoding(Brackets.Begin); - } - SourceLocation getRAngleLoc() const { - return SourceLocation::getFromRawEncoding(Brackets.End); - } - SourceRange getSourceRange() const { - return SourceRange(getLAngleLoc(), getRAngleLoc()); - } - - /// Gather the default set of type arguments to be substituted for - /// these type parameters when dealing with an unspecialized type. - void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const; - friend TrailingObjects; -}; - -/// ObjCContainerDecl - Represents a container for method declarations. -/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, -/// ObjCProtocolDecl, and ObjCImplDecl. -/// -class ObjCContainerDecl : public NamedDecl, public DeclContext { - void anchor() override; - - SourceLocation AtStart; - - // These two locations in the range mark the end of the method container. - // The first points to the '@' token, and the second to the 'end' token. - SourceRange AtEnd; -public: - - ObjCContainerDecl(Kind DK, DeclContext *DC, - IdentifierInfo *Id, SourceLocation nameLoc, - SourceLocation atStartLoc) - : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {} - - // Iterator access to properties. - typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>> - prop_range; - - prop_range properties() const { return prop_range(prop_begin(), prop_end()); } - prop_iterator prop_begin() const { - return prop_iterator(decls_begin()); - } - prop_iterator prop_end() const { - return prop_iterator(decls_end()); - } - - // Iterator access to instance/class methods. - typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>> - method_range; - - method_range methods() const { - return method_range(meth_begin(), meth_end()); - } - method_iterator meth_begin() const { - return method_iterator(decls_begin()); - } - method_iterator meth_end() const { - return method_iterator(decls_end()); - } - - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isInstanceMethod> - instmeth_iterator; - typedef llvm::iterator_range<instmeth_iterator> instmeth_range; - - instmeth_range instance_methods() const { - return instmeth_range(instmeth_begin(), instmeth_end()); - } - instmeth_iterator instmeth_begin() const { - return instmeth_iterator(decls_begin()); - } - instmeth_iterator instmeth_end() const { - return instmeth_iterator(decls_end()); - } - - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isClassMethod> - classmeth_iterator; - typedef llvm::iterator_range<classmeth_iterator> classmeth_range; - - classmeth_range class_methods() const { - return classmeth_range(classmeth_begin(), classmeth_end()); - } - classmeth_iterator classmeth_begin() const { - return classmeth_iterator(decls_begin()); - } - classmeth_iterator classmeth_end() const { - return classmeth_iterator(decls_end()); - } - - // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getMethod(Selector Sel, bool isInstance, - bool AllowHidden = false) const; - ObjCMethodDecl *getInstanceMethod(Selector Sel, - bool AllowHidden = false) const { - return getMethod(Sel, true/*isInstance*/, AllowHidden); - } - ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const { - return getMethod(Sel, false/*isInstance*/, AllowHidden); - } - bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; - ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; - - ObjCPropertyDecl * - FindPropertyDeclaration(const IdentifierInfo *PropertyId) const; - - typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap; - - typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*> - ProtocolPropertyMap; - - typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder; - - /// This routine collects list of properties to be implemented in the class. - /// This includes, class's and its conforming protocols' properties. - /// Note, the superclass's properties are not included in the list. - virtual void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const {} - - SourceLocation getAtStartLoc() const { return AtStart; } - void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; } - - // Marks the end of the container. - SourceRange getAtEndRange() const { - return AtEnd; - } - void setAtEndRange(SourceRange atEnd) { - AtEnd = atEnd; - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(AtStart, getAtEndRange().getEnd()); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstObjCContainer && - K <= lastObjCContainer; - } - - static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { - return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D)); - } - static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC)); - } -}; - -/// \brief Represents an ObjC class declaration. -/// -/// For example: -/// -/// \code -/// // MostPrimitive declares no super class (not particularly useful). -/// \@interface MostPrimitive -/// // no instance variables or methods. -/// \@end -/// -/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). -/// \@interface NSResponder : NSObject \<NSCoding> -/// { // instance variables are represented by ObjCIvarDecl. -/// id nextResponder; // nextResponder instance variable. -/// } -/// - (NSResponder *)nextResponder; // return a pointer to NSResponder. -/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer -/// \@end // to an NSEvent. -/// \endcode -/// -/// Unlike C/C++, forward class declarations are accomplished with \@class. -/// Unlike C/C++, \@class allows for a list of classes to be forward declared. -/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes -/// typically inherit from NSObject (an exception is NSProxy). -/// -class ObjCInterfaceDecl : public ObjCContainerDecl - , public Redeclarable<ObjCInterfaceDecl> { - void anchor() override; - - /// TypeForDecl - This indicates the Type object that represents this - /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType - mutable const Type *TypeForDecl; - friend class ASTContext; - - struct DefinitionData { - /// \brief The definition of this class, for quick access from any - /// declaration. - ObjCInterfaceDecl *Definition; - - /// When non-null, this is always an ObjCObjectType. - TypeSourceInfo *SuperClassTInfo; - - /// Protocols referenced in the \@interface declaration - ObjCProtocolList ReferencedProtocols; - - /// Protocols reference in both the \@interface and class extensions. - ObjCList<ObjCProtocolDecl> AllReferencedProtocols; - - /// \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 wherever possible. - ObjCCategoryDecl *CategoryList; - - /// IvarList - List of all ivars defined by this class; including class - /// extensions and implementation. This list is built lazily. - ObjCIvarDecl *IvarList; - - /// \brief Indicates that the contents of this Objective-C class will be - /// completed by the external AST source when required. - mutable bool ExternallyCompleted : 1; - - /// \brief Indicates that the ivar cache does not yet include ivars - /// declared in the implementation. - mutable bool IvarListMissingImplementation : 1; - - /// Indicates that this interface decl contains at least one initializer - /// marked with the 'objc_designated_initializer' attribute. - bool HasDesignatedInitializers : 1; - - enum InheritedDesignatedInitializersState { - /// We didn't calculate whether the designated initializers should be - /// inherited or not. - IDI_Unknown = 0, - /// Designated initializers are inherited for the super class. - IDI_Inherited = 1, - /// The class does not inherit designated initializers. - IDI_NotInherited = 2 - }; - /// One of the \c InheritedDesignatedInitializersState enumeratos. - mutable unsigned InheritedDesignatedInitializers : 2; - - /// \brief The location of the last location in this declaration, before - /// the properties/methods. For example, this will be the '>', '}', or - /// identifier, - SourceLocation EndLoc; - - DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(), - ExternallyCompleted(), - IvarListMissingImplementation(true), - HasDesignatedInitializers(), - InheritedDesignatedInitializers(IDI_Unknown) { } - }; - - ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc, - IdentifierInfo *Id, ObjCTypeParamList *typeParamList, - SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, - bool IsInternal); - - void LoadExternalDefinition() const; - - /// The type parameters associated with this class, if any. - ObjCTypeParamList *TypeParamList; - - /// \brief Contains a pointer to the data associated with this class, - /// which will be NULL if this class has not yet been defined. - /// - /// The bit indicates when we don't need to check for out-of-date - /// declarations. It will be set unless modules are enabled. - llvm::PointerIntPair<DefinitionData *, 1, bool> Data; - - DefinitionData &data() const { - assert(Data.getPointer() && "Declaration has no definition!"); - return *Data.getPointer(); - } - - /// \brief Allocate the definition data for this class. - void allocateDefinitionData(); - - typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base; - ObjCInterfaceDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - ObjCInterfaceDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - ObjCInterfaceDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation atLoc, - IdentifierInfo *Id, - ObjCTypeParamList *typeParamList, - ObjCInterfaceDecl *PrevDecl, - SourceLocation ClassLoc = SourceLocation(), - bool isInternal = false); - - static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - - /// Retrieve the type parameters of this class. - /// - /// This function looks for a type parameter list for the given - /// class; if the class has been declared (with \c \@class) but not - /// defined (with \c \@interface), it will search for a declaration that - /// has type parameters, skipping any declarations that do not. - ObjCTypeParamList *getTypeParamList() const; - - /// Set the type parameters of this class. - /// - /// This function is used by the AST importer, which must import the type - /// parameters after creating their DeclContext to avoid loops. - void setTypeParamList(ObjCTypeParamList *TPL); - - /// Retrieve the type parameters written on this particular declaration of - /// the class. - ObjCTypeParamList *getTypeParamListAsWritten() const { - return TypeParamList; - } - - SourceRange getSourceRange() const override LLVM_READONLY { - if (isThisDeclarationADefinition()) - return ObjCContainerDecl::getSourceRange(); - - return SourceRange(getAtStartLoc(), getLocation()); - } - - /// \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(); - - /// Indicate that this interface decl contains at least one initializer - /// marked with the 'objc_designated_initializer' attribute. - void setHasDesignatedInitializers(); - - /// Returns true if this interface decl contains at least one initializer - /// marked with the 'objc_designated_initializer' attribute. - bool hasDesignatedInitializers() const; - - /// Returns true if this interface decl declares a designated initializer - /// or it inherites one from its super class. - bool declaresOrInheritsDesignatedInitializers() const { - return hasDesignatedInitializers() || inheritsDesignatedInitializers(); - } - - const ObjCProtocolList &getReferencedProtocols() const { - assert(hasDefinition() && "Caller did not check for forward reference!"); - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().ReferencedProtocols; - } - - ObjCImplementationDecl *getImplementation() const; - void setImplementation(ObjCImplementationDecl *ImplD); - - ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; - - // Get the local instance/class method declared in a category. - ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const; - ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const; - ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const { - return isInstance ? getCategoryInstanceMethod(Sel) - : getCategoryClassMethod(Sel); - } - - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; - - protocol_range protocols() const { - return protocol_range(protocol_begin(), protocol_end()); - } - protocol_iterator protocol_begin() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return protocol_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().ReferencedProtocols.begin(); - } - protocol_iterator protocol_end() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return protocol_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().ReferencedProtocols.end(); - } - - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; - - protocol_loc_range protocol_locs() const { - return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); - } - protocol_loc_iterator protocol_loc_begin() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return protocol_loc_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().ReferencedProtocols.loc_begin(); - } - - protocol_loc_iterator protocol_loc_end() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return protocol_loc_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().ReferencedProtocols.loc_end(); - } - - typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; - typedef llvm::iterator_range<all_protocol_iterator> all_protocol_range; - - all_protocol_range all_referenced_protocols() const { - return all_protocol_range(all_referenced_protocol_begin(), - all_referenced_protocol_end()); - } - all_protocol_iterator all_referenced_protocol_begin() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return all_protocol_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().AllReferencedProtocols.empty() - ? protocol_begin() - : data().AllReferencedProtocols.begin(); - } - all_protocol_iterator all_referenced_protocol_end() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return all_protocol_iterator(); - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().AllReferencedProtocols.empty() - ? protocol_end() - : data().AllReferencedProtocols.end(); - } - - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; - - ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } - ivar_iterator ivar_begin() const { - if (const ObjCInterfaceDecl *Def = getDefinition()) - return ivar_iterator(Def->decls_begin()); - - // FIXME: Should make sure no callers ever do this. - return ivar_iterator(); - } - ivar_iterator ivar_end() const { - if (const ObjCInterfaceDecl *Def = getDefinition()) - return ivar_iterator(Def->decls_end()); - - // FIXME: Should make sure no callers ever do this. - return ivar_iterator(); - } - - unsigned ivar_size() const { - return std::distance(ivar_begin(), ivar_end()); - } - - bool ivar_empty() const { return ivar_begin() == ivar_end(); } - - ObjCIvarDecl *all_declared_ivar_begin(); - const ObjCIvarDecl *all_declared_ivar_begin() const { - // Even though this modifies IvarList, it's conceptually const: - // the ivar chain is essentially a cached property of ObjCInterfaceDecl. - return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin(); - } - void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; } - - /// setProtocolList - Set the list of protocols that this interface - /// implements. - void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, - const SourceLocation *Locs, ASTContext &C) { - data().ReferencedProtocols.set(List, Num, Locs, C); - } - - /// mergeClassExtensionProtocolList - Merge class extension's protocol list - /// into the protocol list for this class. - void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, - unsigned Num, - ASTContext &C); - - /// Produce a name to be used for class's metadata. It comes either via - /// objc_runtime_name attribute or class name. - StringRef getObjCRuntimeNameAsString() const; - - /// Returns the designated initializers for the interface. - /// - /// If this declaration does not have methods marked as designated - /// initializers then the interface inherits the designated initializers of - /// its super class. - void getDesignatedInitializers( - llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const; - - /// Returns true if the given selector is a designated initializer for the - /// interface. - /// - /// If this declaration does not have methods marked as designated - /// initializers then the interface inherits the designated initializers of - /// its super class. - /// - /// \param InitMethod if non-null and the function returns true, it receives - /// the method that was marked as a designated initializer. - bool - isDesignatedInitializer(Selector Sel, - const ObjCMethodDecl **InitMethod = nullptr) const; - - /// \brief Determine whether this particular declaration of this class is - /// actually also a definition. - bool isThisDeclarationADefinition() const { - return getDefinition() == this; - } - - /// \brief Determine whether this class has been defined. - bool hasDefinition() const { - // If the name of this class is out-of-date, bring it up-to-date, which - // might bring in a definition. - // Note: a null value indicates that we don't have a definition and that - // modules are enabled. - if (!Data.getOpaqueValue()) - getMostRecentDecl(); - - return Data.getPointer(); - } - - /// \brief Retrieve the definition of this class, or NULL if this class - /// has been forward-declared (with \@class) but not yet defined (with - /// \@interface). - ObjCInterfaceDecl *getDefinition() { - return hasDefinition()? Data.getPointer()->Definition : nullptr; - } - - /// \brief Retrieve the definition of this class, or NULL if this class - /// has been forward-declared (with \@class) but not yet defined (with - /// \@interface). - const ObjCInterfaceDecl *getDefinition() const { - return hasDefinition()? Data.getPointer()->Definition : nullptr; - } - - /// \brief Starts the definition of this Objective-C class, taking it from - /// a forward declaration (\@class) to a definition (\@interface). - void startDefinition(); - - /// Retrieve the superclass type. - const ObjCObjectType *getSuperClassType() const { - if (TypeSourceInfo *TInfo = getSuperClassTInfo()) - return TInfo->getType()->castAs<ObjCObjectType>(); - - return nullptr; - } - - // Retrieve the type source information for the superclass. - TypeSourceInfo *getSuperClassTInfo() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return nullptr; - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().SuperClassTInfo; - } - - // Retrieve the declaration for the superclass of this class, which - // does not include any type arguments that apply to the superclass. - ObjCInterfaceDecl *getSuperClass() const; - - void setSuperClass(TypeSourceInfo *superClass) { - data().SuperClassTInfo = superClass; - } - - /// \brief Iterator that walks over the list of categories, filtering out - /// those that do not meet specific criteria. - /// - /// This class template is used for the various permutations of category - /// and extension iterators. - template<bool (*Filter)(ObjCCategoryDecl *)> - class filtered_category_iterator { - ObjCCategoryDecl *Current; - - void findAcceptableCategory(); - - public: - typedef ObjCCategoryDecl * value_type; - typedef value_type reference; - typedef value_type pointer; - typedef std::ptrdiff_t difference_type; - typedef std::input_iterator_tag iterator_category; - - filtered_category_iterator() : Current(nullptr) { } - explicit filtered_category_iterator(ObjCCategoryDecl *Current) - : Current(Current) - { - findAcceptableCategory(); - } - - reference operator*() const { return Current; } - pointer operator->() const { return Current; } - - filtered_category_iterator &operator++(); - - filtered_category_iterator operator++(int) { - filtered_category_iterator Tmp = *this; - ++(*this); - return Tmp; - } - - friend bool operator==(filtered_category_iterator X, - filtered_category_iterator Y) { - return X.Current == Y.Current; - } - - friend bool operator!=(filtered_category_iterator X, - filtered_category_iterator Y) { - return X.Current != Y.Current; - } - }; - -private: - /// \brief Test whether the given category is visible. - /// - /// Used in the \c visible_categories_iterator. - static bool isVisibleCategory(ObjCCategoryDecl *Cat); - -public: - /// \brief Iterator that walks over the list of categories and extensions - /// that are visible, i.e., not hidden in a non-imported submodule. - typedef filtered_category_iterator<isVisibleCategory> - visible_categories_iterator; - - typedef llvm::iterator_range<visible_categories_iterator> - visible_categories_range; - - visible_categories_range visible_categories() const { - return visible_categories_range(visible_categories_begin(), - visible_categories_end()); - } - - /// \brief Retrieve an iterator to the beginning of the visible-categories - /// list. - visible_categories_iterator visible_categories_begin() const { - return visible_categories_iterator(getCategoryListRaw()); - } - - /// \brief Retrieve an iterator to the end of the visible-categories list. - visible_categories_iterator visible_categories_end() const { - return visible_categories_iterator(); - } - - /// \brief Determine whether the visible-categories list is empty. - bool visible_categories_empty() const { - return visible_categories_begin() == visible_categories_end(); - } - -private: - /// \brief Test whether the given category... is a category. - /// - /// Used in the \c known_categories_iterator. - static bool isKnownCategory(ObjCCategoryDecl *) { return true; } - -public: - /// \brief Iterator that walks over all of the known categories and - /// extensions, including those that are hidden. - typedef filtered_category_iterator<isKnownCategory> known_categories_iterator; - typedef llvm::iterator_range<known_categories_iterator> - known_categories_range; - - known_categories_range known_categories() const { - return known_categories_range(known_categories_begin(), - known_categories_end()); - } - - /// \brief Retrieve an iterator to the beginning of the known-categories - /// list. - known_categories_iterator known_categories_begin() const { - return known_categories_iterator(getCategoryListRaw()); - } - - /// \brief Retrieve an iterator to the end of the known-categories list. - known_categories_iterator known_categories_end() const { - return known_categories_iterator(); - } - - /// \brief Determine whether the known-categories list is empty. - bool known_categories_empty() const { - return known_categories_begin() == known_categories_end(); - } - -private: - /// \brief Test whether the given category is a visible extension. - /// - /// Used in the \c visible_extensions_iterator. - static bool isVisibleExtension(ObjCCategoryDecl *Cat); - -public: - /// \brief Iterator that walks over all of the visible extensions, skipping - /// any that are known but hidden. - typedef filtered_category_iterator<isVisibleExtension> - visible_extensions_iterator; - - typedef llvm::iterator_range<visible_extensions_iterator> - visible_extensions_range; - - visible_extensions_range visible_extensions() const { - return visible_extensions_range(visible_extensions_begin(), - visible_extensions_end()); - } - - /// \brief Retrieve an iterator to the beginning of the visible-extensions - /// list. - visible_extensions_iterator visible_extensions_begin() const { - return visible_extensions_iterator(getCategoryListRaw()); - } - - /// \brief Retrieve an iterator to the end of the visible-extensions list. - visible_extensions_iterator visible_extensions_end() const { - return visible_extensions_iterator(); - } - - /// \brief Determine whether the visible-extensions list is empty. - bool visible_extensions_empty() const { - return visible_extensions_begin() == visible_extensions_end(); - } - -private: - /// \brief Test whether the given category is an extension. - /// - /// Used in the \c known_extensions_iterator. - static bool isKnownExtension(ObjCCategoryDecl *Cat); - -public: - /// \brief Iterator that walks over all of the known extensions. - typedef filtered_category_iterator<isKnownExtension> - known_extensions_iterator; - typedef llvm::iterator_range<known_extensions_iterator> - known_extensions_range; - - known_extensions_range known_extensions() const { - return known_extensions_range(known_extensions_begin(), - known_extensions_end()); - } - - /// \brief Retrieve an iterator to the beginning of the known-extensions - /// list. - known_extensions_iterator known_extensions_begin() const { - return known_extensions_iterator(getCategoryListRaw()); - } - - /// \brief Retrieve an iterator to the end of the known-extensions list. - known_extensions_iterator known_extensions_end() const { - return known_extensions_iterator(); - } - - /// \brief Determine whether the known-extensions list is empty. - bool known_extensions_empty() const { - return known_extensions_begin() == known_extensions_end(); - } - - /// \brief Retrieve the raw pointer to the start of the category/extension - /// list. - ObjCCategoryDecl* getCategoryListRaw() const { - // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return nullptr; - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return data().CategoryList; - } - - /// \brief Set the raw pointer to the start of the category/extension - /// list. - void setCategoryListRaw(ObjCCategoryDecl *category) { - data().CategoryList = category; - } - - ObjCPropertyDecl - *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; - - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; - - /// isSuperClassOf - Return true if this class is the specified class or is a - /// super class of the specified interface class. - bool isSuperClassOf(const ObjCInterfaceDecl *I) const { - // If RHS is derived from LHS it is OK; else it is not OK. - while (I != nullptr) { - if (declaresSameEntity(this, I)) - return true; - - I = I->getSuperClass(); - } - return false; - } - - /// isArcWeakrefUnavailable - Checks for a class or one of its super classes - /// to be incompatible with __weak references. Returns true if it is. - bool isArcWeakrefUnavailable() const; - - /// isObjCRequiresPropertyDefs - Checks that a class or one of its super - /// classes must not be auto-synthesized. Returns class decl. if it must not - /// be; 0, otherwise. - const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const; - - ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, - ObjCInterfaceDecl *&ClassDeclared); - ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) { - ObjCInterfaceDecl *ClassDeclared; - return lookupInstanceVariable(IVarName, ClassDeclared); - } - - ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name); - - // Lookup a method. First, we search locally. If a method isn't - // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, - bool shallowCategoryLookup = false, - bool followSuper = true, - const ObjCCategoryDecl *C = nullptr) const; - - /// Lookup an instance method for a given selector. - ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { - return lookupMethod(Sel, true/*isInstance*/); - } - - /// Lookup a class method for a given selector. - ObjCMethodDecl *lookupClassMethod(Selector Sel) const { - return lookupMethod(Sel, false/*isInstance*/); - } - ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); - - /// \brief Lookup a method in the classes implementation hierarchy. - ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, - bool Instance=true) const; - - ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) { - return lookupPrivateMethod(Sel, false); - } - - /// \brief Lookup a setter or getter in the class hierarchy, - /// including in all categories except for category passed - /// as argument. - ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, - const ObjCCategoryDecl *Cat) const { - return lookupMethod(Sel, true/*isInstance*/, - false/*shallowCategoryLookup*/, - true /* followsSuper */, - Cat); - } - - SourceLocation getEndOfDefinitionLoc() const { - if (!hasDefinition()) - return getLocation(); - - return data().EndLoc; - } - - void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; } - - /// Retrieve the starting location of the superclass. - SourceLocation getSuperClassLoc() const; - - /// isImplicitInterfaceDecl - check that this is an implicitly declared - /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation - /// declaration without an \@interface declaration. - bool isImplicitInterfaceDecl() const { - return hasDefinition() ? data().Definition->isImplicit() : isImplicit(); - } - - /// ClassImplementsProtocol - Checks that 'lProto' protocol - /// has been implemented in IDecl class, its super class or categories (if - /// lookupCategory is true). - bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, - bool lookupCategory, - bool RHSIsQualifiedID = false); - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - /// Retrieves the canonical declaration of this Objective-C class. - ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); } - const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); } - - // Low-level accessor - 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 classofKind(Kind K) { return K == ObjCInterface; } - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; - -private: - const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const; - bool inheritsDesignatedInitializers() const; -}; - -/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC -/// instance variables are identical to C. The only exception is Objective-C -/// supports C++ style access control. For example: -/// -/// \@interface IvarExample : NSObject -/// { -/// id defaultToProtected; -/// \@public: -/// id canBePublic; // same as C++. -/// \@protected: -/// id canBeProtected; // same as C++. -/// \@package: -/// id canBePackage; // framework visibility (not available in C++). -/// } -/// -class ObjCIvarDecl : public FieldDecl { - void anchor() override; - -public: - enum AccessControl { - None, Private, Protected, Public, Package - }; - -private: - ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized) - : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, - /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), - NextIvar(nullptr), DeclAccess(ac), Synthesized(synthesized) {} - -public: - static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, - AccessControl ac, Expr *BW = nullptr, - bool synthesized=false); - - static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// \brief Return the class interface that this ivar is logically contained - /// in; this is either the interface where the ivar was declared, or the - /// interface the ivar is conceptually a part of in the case of synthesized - /// ivars. - const ObjCInterfaceDecl *getContainingInterface() const; - - ObjCIvarDecl *getNextIvar() { return NextIvar; } - const ObjCIvarDecl *getNextIvar() const { return NextIvar; } - void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } - - void setAccessControl(AccessControl ac) { DeclAccess = ac; } - - AccessControl getAccessControl() const { return AccessControl(DeclAccess); } - - AccessControl getCanonicalAccessControl() const { - return DeclAccess == None ? Protected : AccessControl(DeclAccess); - } - - void setSynthesize(bool synth) { Synthesized = synth; } - bool getSynthesize() const { return Synthesized; } - - /// Retrieve the type of this instance variable when viewed as a member of a - /// specific object type. - QualType getUsageType(QualType objectType) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCIvar; } -private: - /// NextIvar - Next Ivar in the list of ivars declared in class; class's - /// extensions and class's implementation - ObjCIvarDecl *NextIvar; - - // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum - unsigned DeclAccess : 3; - unsigned Synthesized : 1; -}; - - -/// \brief Represents a field declaration created by an \@defs(...). -class ObjCAtDefsFieldDecl : public FieldDecl { - void anchor() override; - ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, - /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ? - BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {} - -public: - static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, Expr *BW); - - static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCAtDefsField; } -}; - -/// \brief Represents an Objective-C protocol declaration. -/// -/// Objective-C protocols declare a pure abstract type (i.e., no instance -/// variables are permitted). Protocols originally drew inspiration from -/// C++ pure virtual functions (a C++ feature with nice semantics and lousy -/// syntax:-). Here is an example: -/// -/// \code -/// \@protocol NSDraggingInfo <refproto1, refproto2> -/// - (NSWindow *)draggingDestinationWindow; -/// - (NSImage *)draggedImage; -/// \@end -/// \endcode -/// -/// This says that NSDraggingInfo requires two methods and requires everything -/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as -/// well. -/// -/// \code -/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo> -/// \@end -/// \endcode -/// -/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and -/// protocols are in distinct namespaces. For example, Cocoa defines both -/// an NSObject protocol and class (which isn't allowed in Java). As a result, -/// protocols are referenced using angle brackets as follows: -/// -/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; -/// -class ObjCProtocolDecl : public ObjCContainerDecl, - public Redeclarable<ObjCProtocolDecl> { - void anchor() override; - - struct DefinitionData { - // \brief The declaration that defines this protocol. - ObjCProtocolDecl *Definition; - - /// \brief Referenced protocols - ObjCProtocolList ReferencedProtocols; - }; - - /// \brief Contains a pointer to the data associated with this class, - /// which will be NULL if this class has not yet been defined. - /// - /// The bit indicates when we don't need to check for out-of-date - /// declarations. It will be set unless modules are enabled. - llvm::PointerIntPair<DefinitionData *, 1, bool> Data; - - DefinitionData &data() const { - assert(Data.getPointer() && "Objective-C protocol has no definition!"); - return *Data.getPointer(); - } - - ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, - SourceLocation nameLoc, SourceLocation atStartLoc, - ObjCProtocolDecl *PrevDecl); - - void allocateDefinitionData(); - - typedef Redeclarable<ObjCProtocolDecl> redeclarable_base; - ObjCProtocolDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - ObjCProtocolDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - ObjCProtocolDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -public: - static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, - IdentifierInfo *Id, - SourceLocation nameLoc, - SourceLocation atStartLoc, - ObjCProtocolDecl *PrevDecl); - - static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - const ObjCProtocolList &getReferencedProtocols() const { - assert(hasDefinition() && "No definition available!"); - return data().ReferencedProtocols; - } - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; - - protocol_range protocols() const { - return protocol_range(protocol_begin(), protocol_end()); - } - protocol_iterator protocol_begin() const { - if (!hasDefinition()) - return protocol_iterator(); - - return data().ReferencedProtocols.begin(); - } - protocol_iterator protocol_end() const { - if (!hasDefinition()) - return protocol_iterator(); - - return data().ReferencedProtocols.end(); - } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; - - protocol_loc_range protocol_locs() const { - return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); - } - protocol_loc_iterator protocol_loc_begin() const { - if (!hasDefinition()) - return protocol_loc_iterator(); - - return data().ReferencedProtocols.loc_begin(); - } - protocol_loc_iterator protocol_loc_end() const { - if (!hasDefinition()) - return protocol_loc_iterator(); - - return data().ReferencedProtocols.loc_end(); - } - unsigned protocol_size() const { - if (!hasDefinition()) - return 0; - - return data().ReferencedProtocols.size(); - } - - /// setProtocolList - Set the list of protocols that this interface - /// implements. - void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, - const SourceLocation *Locs, ASTContext &C) { - assert(hasDefinition() && "Protocol is not defined"); - data().ReferencedProtocols.set(List, Num, Locs, C); - } - - ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); - - // Lookup a method. First, we search locally. If a method isn't - // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const; - ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { - return lookupMethod(Sel, true/*isInstance*/); - } - ObjCMethodDecl *lookupClassMethod(Selector Sel) const { - return lookupMethod(Sel, false/*isInstance*/); - } - - /// \brief Determine whether this protocol has a definition. - bool hasDefinition() const { - // If the name of this protocol is out-of-date, bring it up-to-date, which - // might bring in a definition. - // Note: a null value indicates that we don't have a definition and that - // modules are enabled. - if (!Data.getOpaqueValue()) - getMostRecentDecl(); - - return Data.getPointer(); - } - - /// \brief Retrieve the definition of this protocol, if any. - ObjCProtocolDecl *getDefinition() { - return hasDefinition()? Data.getPointer()->Definition : nullptr; - } - - /// \brief Retrieve the definition of this protocol, if any. - const ObjCProtocolDecl *getDefinition() const { - return hasDefinition()? Data.getPointer()->Definition : nullptr; - } - - /// \brief Determine whether this particular declaration is also the - /// definition. - bool isThisDeclarationADefinition() const { - return getDefinition() == this; - } - - /// \brief Starts the definition of this Objective-C protocol. - void startDefinition(); - - /// Produce a name to be used for protocol's metadata. It comes either via - /// objc_runtime_name attribute or protocol name. - StringRef getObjCRuntimeNameAsString() const; - - SourceRange getSourceRange() const override LLVM_READONLY { - if (isThisDeclarationADefinition()) - return ObjCContainerDecl::getSourceRange(); - - return SourceRange(getAtStartLoc(), getLocation()); - } - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - /// Retrieves the canonical declaration of this Objective-C protocol. - ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); } - const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); } - - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; - - void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, - ProtocolPropertyMap &PM) const; - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCProtocol; } - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// ObjCCategoryDecl - Represents a category declaration. A category allows -/// you to add methods to an existing class (without subclassing or modifying -/// the original class interface or implementation:-). Categories don't allow -/// you to add instance data. The following example adds "myMethod" to all -/// NSView's within a process: -/// -/// \@interface NSView (MyViewMethods) -/// - myMethod; -/// \@end -/// -/// Categories also allow you to split the implementation of a class across -/// several files (a feature more naturally supported in C++). -/// -/// Categories were originally inspired by dynamic languages such as Common -/// Lisp and Smalltalk. More traditional class-based languages (C++, Java) -/// don't support this level of dynamism, which is both powerful and dangerous. -/// -class ObjCCategoryDecl : public ObjCContainerDecl { - void anchor() override; - - /// Interface belonging to this category - ObjCInterfaceDecl *ClassInterface; - - /// The type parameters associated with this category, if any. - ObjCTypeParamList *TypeParamList; - - /// referenced protocols in this category. - ObjCProtocolList ReferencedProtocols; - - /// Next category belonging to this class. - /// FIXME: this should not be a singly-linked list. Move storage elsewhere. - ObjCCategoryDecl *NextClassCategory; - - /// \brief The location of the category name in this declaration. - SourceLocation CategoryNameLoc; - - /// class extension may have private ivars. - SourceLocation IvarLBraceLoc; - SourceLocation IvarRBraceLoc; - - ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, - SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, - IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, - ObjCTypeParamList *typeParamList, - SourceLocation IvarLBraceLoc=SourceLocation(), - SourceLocation IvarRBraceLoc=SourceLocation()); - -public: - - static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation AtLoc, - SourceLocation ClassNameLoc, - SourceLocation CategoryNameLoc, - IdentifierInfo *Id, - ObjCInterfaceDecl *IDecl, - ObjCTypeParamList *typeParamList, - SourceLocation IvarLBraceLoc=SourceLocation(), - SourceLocation IvarRBraceLoc=SourceLocation()); - static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } - const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } - - /// Retrieve the type parameter list associated with this category or - /// extension. - ObjCTypeParamList *getTypeParamList() const { return TypeParamList; } - - /// Set the type parameters of this category. - /// - /// This function is used by the AST importer, which must import the type - /// parameters after creating their DeclContext to avoid loops. - void setTypeParamList(ObjCTypeParamList *TPL); - - - ObjCCategoryImplDecl *getImplementation() const; - void setImplementation(ObjCCategoryImplDecl *ImplD); - - /// setProtocolList - Set the list of protocols that this interface - /// implements. - void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, - const SourceLocation *Locs, ASTContext &C) { - ReferencedProtocols.set(List, Num, Locs, C); - } - - const ObjCProtocolList &getReferencedProtocols() const { - return ReferencedProtocols; - } - - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; - - protocol_range protocols() const { - return protocol_range(protocol_begin(), protocol_end()); - } - protocol_iterator protocol_begin() const { - return ReferencedProtocols.begin(); - } - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; - - protocol_loc_range protocol_locs() const { - return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); - } - protocol_loc_iterator protocol_loc_begin() const { - return ReferencedProtocols.loc_begin(); - } - protocol_loc_iterator protocol_loc_end() const { - return ReferencedProtocols.loc_end(); - } - - ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } - - /// \brief Retrieve the pointer to the next stored category (or extension), - /// which may be hidden. - ObjCCategoryDecl *getNextClassCategoryRaw() const { - return NextClassCategory; - } - - bool IsClassExtension() const { return getIdentifier() == nullptr; } - - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; - - ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } - ivar_iterator ivar_begin() const { - return ivar_iterator(decls_begin()); - } - ivar_iterator ivar_end() const { - return ivar_iterator(decls_end()); - } - unsigned ivar_size() const { - return std::distance(ivar_begin(), ivar_end()); - } - bool ivar_empty() const { - return ivar_begin() == ivar_end(); - } - - SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } - void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; } - - void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } - SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } - void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } - SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCCategory; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -class ObjCImplDecl : public ObjCContainerDecl { - void anchor() override; - - /// Class interface for this class/category implementation - ObjCInterfaceDecl *ClassInterface; - -protected: - ObjCImplDecl(Kind DK, DeclContext *DC, - ObjCInterfaceDecl *classInterface, - SourceLocation nameLoc, SourceLocation atStartLoc) - : ObjCContainerDecl(DK, DC, - classInterface? classInterface->getIdentifier() - : nullptr, - nameLoc, atStartLoc), - ClassInterface(classInterface) {} - -public: - const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } - ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } - void setClassInterface(ObjCInterfaceDecl *IFace); - - void addInstanceMethod(ObjCMethodDecl *method) { - // FIXME: Context should be set correctly before we get here. - method->setLexicalDeclContext(this); - addDecl(method); - } - void addClassMethod(ObjCMethodDecl *method) { - // FIXME: Context should be set correctly before we get here. - method->setLexicalDeclContext(this); - addDecl(method); - } - - void addPropertyImplementation(ObjCPropertyImplDecl *property); - - ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; - ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; - - // Iterator access to properties. - typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>> - propimpl_range; - - propimpl_range property_impls() const { - return propimpl_range(propimpl_begin(), propimpl_end()); - } - propimpl_iterator propimpl_begin() const { - return propimpl_iterator(decls_begin()); - } - propimpl_iterator propimpl_end() const { - return propimpl_iterator(decls_end()); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstObjCImpl && K <= lastObjCImpl; - } -}; - -/// ObjCCategoryImplDecl - An object of this class encapsulates a category -/// \@implementation declaration. If a category class has declaration of a -/// property, its implementation must be specified in the category's -/// \@implementation declaration. Example: -/// \@interface I \@end -/// \@interface I(CATEGORY) -/// \@property int p1, d1; -/// \@end -/// \@implementation I(CATEGORY) -/// \@dynamic p1,d1; -/// \@end -/// -/// ObjCCategoryImplDecl -class ObjCCategoryImplDecl : public ObjCImplDecl { - void anchor() override; - - // Category name - IdentifierInfo *Id; - - // Category name location - SourceLocation CategoryNameLoc; - - ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id, - ObjCInterfaceDecl *classInterface, - SourceLocation nameLoc, SourceLocation atStartLoc, - SourceLocation CategoryNameLoc) - : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc), - Id(Id), CategoryNameLoc(CategoryNameLoc) {} -public: - static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, - IdentifierInfo *Id, - ObjCInterfaceDecl *classInterface, - SourceLocation nameLoc, - SourceLocation atStartLoc, - SourceLocation CategoryNameLoc); - static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// getIdentifier - Get the identifier that names the category - /// interface associated with this implementation. - /// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier() - /// with a different meaning. For example: - /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() - /// returns the class interface name, whereas - /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() - /// returns the category name. - IdentifierInfo *getIdentifier() const { - return Id; - } - void setIdentifier(IdentifierInfo *II) { Id = II; } - - ObjCCategoryDecl *getCategoryDecl() const; - - SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } - - /// getName - Get the name of identifier for the class interface associated - /// with this implementation as a StringRef. - // - // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different - // meaning. - StringRef getName() const { return Id ? Id->getName() : StringRef(); } - - /// @brief Get the name of the class associated with this interface. - // - // FIXME: Deprecated, move clients to getName(). - std::string getNameAsString() const { - return getName(); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); - -/// ObjCImplementationDecl - Represents a class definition - this is where -/// method definitions are specified. For example: -/// -/// @code -/// \@implementation MyClass -/// - (void)myMethod { /* do something */ } -/// \@end -/// @endcode -/// -/// In a non-fragile runtime, instance variables can appear in the class -/// interface, class extensions (nameless categories), and in the implementation -/// itself, as well as being synthesized as backing storage for properties. -/// -/// In a fragile runtime, instance variables are specified in the class -/// interface, \em not in the implementation. Nevertheless (for legacy reasons), -/// we allow instance variables to be specified in the implementation. When -/// specified, they need to be \em identical to the interface. -class ObjCImplementationDecl : public ObjCImplDecl { - void anchor() override; - /// Implementation Class's super class. - ObjCInterfaceDecl *SuperClass; - SourceLocation SuperLoc; - - /// \@implementation may have private ivars. - SourceLocation IvarLBraceLoc; - SourceLocation IvarRBraceLoc; - - /// Support for ivar initialization. - /// \brief The arguments used to initialize the ivars - LazyCXXCtorInitializersPtr IvarInitializers; - unsigned NumIvarInitializers; - - /// Do the ivars of this class require initialization other than - /// zero-initialization? - bool HasNonZeroConstructors : 1; - - /// Do the ivars of this class require non-trivial destruction? - bool HasDestructors : 1; - - ObjCImplementationDecl(DeclContext *DC, - ObjCInterfaceDecl *classInterface, - ObjCInterfaceDecl *superDecl, - SourceLocation nameLoc, SourceLocation atStartLoc, - SourceLocation superLoc = SourceLocation(), - SourceLocation IvarLBraceLoc=SourceLocation(), - SourceLocation IvarRBraceLoc=SourceLocation()) - : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), - SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc), - IvarRBraceLoc(IvarRBraceLoc), - IvarInitializers(nullptr), NumIvarInitializers(0), - HasNonZeroConstructors(false), HasDestructors(false) {} -public: - static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, - ObjCInterfaceDecl *classInterface, - ObjCInterfaceDecl *superDecl, - SourceLocation nameLoc, - SourceLocation atStartLoc, - SourceLocation superLoc = SourceLocation(), - SourceLocation IvarLBraceLoc=SourceLocation(), - SourceLocation IvarRBraceLoc=SourceLocation()); - - static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// init_iterator - Iterates through the ivar initializer list. - typedef CXXCtorInitializer **init_iterator; - - /// init_const_iterator - Iterates through the ivar initializer list. - typedef CXXCtorInitializer * const * init_const_iterator; - - typedef llvm::iterator_range<init_iterator> init_range; - typedef llvm::iterator_range<init_const_iterator> init_const_range; - - init_range inits() { return init_range(init_begin(), init_end()); } - init_const_range inits() const { - return init_const_range(init_begin(), init_end()); - } - - /// init_begin() - Retrieve an iterator to the first initializer. - init_iterator init_begin() { - const auto *ConstThis = this; - return const_cast<init_iterator>(ConstThis->init_begin()); - } - /// begin() - Retrieve an iterator to the first initializer. - init_const_iterator init_begin() const; - - /// init_end() - Retrieve an iterator past the last initializer. - init_iterator init_end() { - return init_begin() + NumIvarInitializers; - } - /// end() - Retrieve an iterator past the last initializer. - init_const_iterator init_end() const { - return init_begin() + NumIvarInitializers; - } - /// getNumArgs - Number of ivars which must be initialized. - unsigned getNumIvarInitializers() const { - return NumIvarInitializers; - } - - void setNumIvarInitializers(unsigned numNumIvarInitializers) { - NumIvarInitializers = numNumIvarInitializers; - } - - void setIvarInitializers(ASTContext &C, - CXXCtorInitializer ** initializers, - unsigned numInitializers); - - /// Do any of the ivars of this class (not counting its base classes) - /// require construction other than zero-initialization? - bool hasNonZeroConstructors() const { return HasNonZeroConstructors; } - void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; } - - /// Do any of the ivars of this class (not counting its base classes) - /// require non-trivial destruction? - bool hasDestructors() const { return HasDestructors; } - void setHasDestructors(bool val) { HasDestructors = val; } - - /// getIdentifier - Get the identifier that names the class - /// interface associated with this implementation. - IdentifierInfo *getIdentifier() const { - return getClassInterface()->getIdentifier(); - } - - /// getName - Get the name of identifier for the class interface associated - /// with this implementation as a StringRef. - // - // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different - // meaning. - StringRef getName() const { - assert(getIdentifier() && "Name is not a simple identifier"); - return getIdentifier()->getName(); - } - - /// @brief Get the name of the class associated with this interface. - // - // FIXME: Move to StringRef API. - std::string getNameAsString() const { - return getName(); - } - - /// Produce a name to be used for class's metadata. It comes either via - /// class's objc_runtime_name attribute or class name. - StringRef getObjCRuntimeNameAsString() const; - - const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } - ObjCInterfaceDecl *getSuperClass() { return SuperClass; } - SourceLocation getSuperClassLoc() const { return SuperLoc; } - - void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } - - void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } - SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } - void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } - SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } - - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; - - ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } - ivar_iterator ivar_begin() const { - return ivar_iterator(decls_begin()); - } - ivar_iterator ivar_end() const { - return ivar_iterator(decls_end()); - } - unsigned ivar_size() const { - return std::distance(ivar_begin(), ivar_end()); - } - bool ivar_empty() const { - return ivar_begin() == ivar_end(); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCImplementation; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); - -/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is -/// declared as \@compatibility_alias alias class. -class ObjCCompatibleAliasDecl : public NamedDecl { - void anchor() override; - /// Class that this is an alias of. - ObjCInterfaceDecl *AliasedClass; - - ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - ObjCInterfaceDecl* aliasedClass) - : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {} -public: - static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - ObjCInterfaceDecl* aliasedClass); - - static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, - unsigned ID); - - const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } - ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } - void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; } - -}; - -/// \brief Represents one property declaration in an Objective-C interface. -/// -/// For example: -/// \code{.mm} -/// \@property (assign, readwrite) int MyProperty; -/// \endcode -class ObjCPropertyDecl : public NamedDecl { - void anchor() override; -public: - enum PropertyAttributeKind { - OBJC_PR_noattr = 0x00, - OBJC_PR_readonly = 0x01, - OBJC_PR_getter = 0x02, - OBJC_PR_assign = 0x04, - OBJC_PR_readwrite = 0x08, - OBJC_PR_retain = 0x10, - OBJC_PR_copy = 0x20, - OBJC_PR_nonatomic = 0x40, - OBJC_PR_setter = 0x80, - OBJC_PR_atomic = 0x100, - OBJC_PR_weak = 0x200, - OBJC_PR_strong = 0x400, - OBJC_PR_unsafe_unretained = 0x800, - /// Indicates that the nullability of the type was spelled with a - /// property attribute rather than a type qualifier. - OBJC_PR_nullability = 0x1000, - OBJC_PR_null_resettable = 0x2000 - // Adding a property should change NumPropertyAttrsBits - }; - - enum { - /// \brief Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 14 - }; - - enum SetterKind { Assign, Retain, Copy, Weak }; - enum PropertyControl { None, Required, Optional }; -private: - SourceLocation AtLoc; // location of \@property - SourceLocation LParenLoc; // location of '(' starting attribute list or null. - QualType DeclType; - TypeSourceInfo *DeclTypeSourceInfo; - unsigned PropertyAttributes : NumPropertyAttrsBits; - unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; - // \@required/\@optional - unsigned PropertyImplementation : 2; - - Selector GetterName; // getter name of NULL if no getter - Selector SetterName; // setter name of NULL if no setter - - ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method - ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method - ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property - - ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation AtLocation, SourceLocation LParenLocation, - QualType T, TypeSourceInfo *TSI, - PropertyControl propControl) - : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), - LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), - PropertyAttributes(OBJC_PR_noattr), - PropertyAttributesAsWritten(OBJC_PR_noattr), - PropertyImplementation(propControl), - GetterName(Selector()), - SetterName(Selector()), - GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), - PropertyIvarDecl(nullptr) {} - -public: - static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, SourceLocation AtLocation, - SourceLocation LParenLocation, - QualType T, - TypeSourceInfo *TSI, - PropertyControl propControl = None); - - static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceLocation getAtLoc() const { return AtLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - - TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; } - - QualType getType() const { return DeclType; } - - void setType(QualType T, TypeSourceInfo *TSI) { - DeclType = T; - DeclTypeSourceInfo = TSI; - } - - /// Retrieve the type when this property is used with a specific base object - /// type. - QualType getUsageType(QualType objectType) const; - - PropertyAttributeKind getPropertyAttributes() const { - return PropertyAttributeKind(PropertyAttributes); - } - void setPropertyAttributes(PropertyAttributeKind PRVal) { - PropertyAttributes |= PRVal; - } - void overwritePropertyAttributes(unsigned PRVal) { - PropertyAttributes = PRVal; - } - - PropertyAttributeKind getPropertyAttributesAsWritten() const { - return PropertyAttributeKind(PropertyAttributesAsWritten); - } - - void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { - PropertyAttributesAsWritten = PRVal; - } - - // Helper methods for accessing attributes. - - /// isReadOnly - Return true iff the property has a setter. - bool isReadOnly() const { - return (PropertyAttributes & OBJC_PR_readonly); - } - - /// isAtomic - Return true if the property is atomic. - bool isAtomic() const { - return (PropertyAttributes & OBJC_PR_atomic); - } - - /// isRetaining - Return true if the property retains its value. - bool isRetaining() const { - return (PropertyAttributes & - (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy)); - } - - /// getSetterKind - Return the method used for doing assignment in - /// the property setter. This is only valid if the property has been - /// defined to have a setter. - SetterKind getSetterKind() const { - if (PropertyAttributes & OBJC_PR_strong) - return getType()->isBlockPointerType() ? Copy : Retain; - if (PropertyAttributes & OBJC_PR_retain) - return Retain; - if (PropertyAttributes & OBJC_PR_copy) - return Copy; - if (PropertyAttributes & OBJC_PR_weak) - return Weak; - return Assign; - } - - Selector getGetterName() const { return GetterName; } - void setGetterName(Selector Sel) { GetterName = Sel; } - - Selector getSetterName() const { return SetterName; } - void setSetterName(Selector Sel) { SetterName = Sel; } - - ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } - void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } - - ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } - void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } - - // Related to \@optional/\@required declared in \@protocol - void setPropertyImplementation(PropertyControl pc) { - PropertyImplementation = pc; - } - PropertyControl getPropertyImplementation() const { - return PropertyControl(PropertyImplementation); - } - - void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { - PropertyIvarDecl = Ivar; - } - ObjCIvarDecl *getPropertyIvarDecl() const { - return PropertyIvarDecl; - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(AtLoc, getLocation()); - } - - /// Get the default name of the synthesized ivar. - IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const; - - /// Lookup a property by name in the specified DeclContext. - static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID); - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCProperty; } -}; - -/// ObjCPropertyImplDecl - Represents implementation declaration of a property -/// in a class or category implementation block. For example: -/// \@synthesize prop1 = ivar1; -/// -class ObjCPropertyImplDecl : public Decl { -public: - enum Kind { - Synthesize, - Dynamic - }; -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; - - /// Null for \@dynamic. Required for \@synthesize. - ObjCIvarDecl *PropertyIvarDecl; - - /// Null for \@dynamic. Non-null if property must be copy-constructed in - /// getter. - Expr *GetterCXXConstructor; - - /// Null for \@dynamic. Non-null if property has assignment operator to call - /// in Setter synthesis. - Expr *SetterCXXAssignment; - - ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, - ObjCPropertyDecl *property, - Kind PK, - ObjCIvarDecl *ivarDecl, - SourceLocation ivarLoc) - : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), - GetterCXXConstructor(nullptr), SetterCXXAssignment(nullptr) { - assert (PK == Dynamic || PropertyIvarDecl); - } - -public: - static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation atLoc, SourceLocation L, - ObjCPropertyDecl *property, - Kind PK, - ObjCIvarDecl *ivarDecl, - SourceLocation ivarLoc); - - static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } - - ObjCPropertyDecl *getPropertyDecl() const { - return PropertyDecl; - } - void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; } - - Kind getPropertyImplementation() const { - return PropertyIvarDecl ? Synthesize : Dynamic; - } - - ObjCIvarDecl *getPropertyIvarDecl() const { - return PropertyIvarDecl; - } - SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; } - - void setPropertyIvarDecl(ObjCIvarDecl *Ivar, - SourceLocation IvarLoc) { - PropertyIvarDecl = Ivar; - this->IvarLoc = IvarLoc; - } - - /// \brief For \@synthesize, returns true if an ivar name was explicitly - /// specified. - /// - /// \code - /// \@synthesize int a = b; // true - /// \@synthesize int a; // false - /// \endcode - bool isIvarNameSpecified() const { - return IvarLoc.isValid() && IvarLoc != getLocation(); - } - - Expr *getGetterCXXConstructor() const { - return GetterCXXConstructor; - } - void setGetterCXXConstructor(Expr *getterCXXConstructor) { - GetterCXXConstructor = getterCXXConstructor; - } - - Expr *getSetterCXXAssignment() const { - return SetterCXXAssignment; - } - void setSetterCXXAssignment(Expr *setterCXXAssignment) { - SetterCXXAssignment = setterCXXAssignment; - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } - - friend class ASTDeclReader; -}; - -template<bool (*Filter)(ObjCCategoryDecl *)> -void -ObjCInterfaceDecl::filtered_category_iterator<Filter>:: -findAcceptableCategory() { - while (Current && !Filter(Current)) - Current = Current->getNextClassCategoryRaw(); -} - -template<bool (*Filter)(ObjCCategoryDecl *)> -inline ObjCInterfaceDecl::filtered_category_iterator<Filter> & -ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() { - Current = Current->getNextClassCategoryRaw(); - findAcceptableCategory(); - return *this; -} - -inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) { - return !Cat->isHidden(); -} - -inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension() && !Cat->isHidden(); -} - -inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension(); -} - -} // end namespace clang -#endif diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h deleted file mode 100644 index 598f418..0000000 --- a/include/clang/AST/DeclOpenMP.h +++ /dev/null @@ -1,91 +0,0 @@ -//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file defines OpenMP nodes for declarative directives. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLOPENMP_H -#define LLVM_CLANG_AST_DECLOPENMP_H - -#include "clang/AST/DeclBase.h" -#include "llvm/ADT/ArrayRef.h" - -namespace clang { -class Expr; - -/// \brief This represents '#pragma omp threadprivate ...' directive. -/// For example, in the following, both 'a' and 'A::b' are threadprivate: -/// -/// \code -/// int a; -/// #pragma omp threadprivate(a) -/// struct A { -/// static int b; -/// #pragma omp threadprivate(b) -/// }; -/// \endcode -/// -class OMPThreadPrivateDecl final - : public Decl, - private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> { - friend class ASTDeclReader; - friend TrailingObjects; - - unsigned NumVars; - - virtual void anchor(); - - OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) : - Decl(DK, DC, L), NumVars(0) { } - - ArrayRef<const Expr *> getVars() const { - return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars); - } - - MutableArrayRef<Expr *> getVars() { - return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars); - } - - void setVars(ArrayRef<Expr *> VL); - -public: - static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - ArrayRef<Expr *> VL); - static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, - unsigned ID, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator varlist_iterator; - typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; - typedef llvm::iterator_range<varlist_iterator> varlist_range; - typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; - - unsigned varlist_size() const { return NumVars; } - bool varlist_empty() const { return NumVars == 0; } - - varlist_range varlists() { - return varlist_range(varlist_begin(), varlist_end()); - } - varlist_const_range varlists() const { - return varlist_const_range(varlist_begin(), varlist_end()); - } - varlist_iterator varlist_begin() { return getVars().begin(); } - varlist_iterator varlist_end() { return getVars().end(); } - varlist_const_iterator varlist_begin() const { return getVars().begin(); } - varlist_const_iterator varlist_end() const { return getVars().end(); } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == OMPThreadPrivate; } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h deleted file mode 100644 index a9109ef..0000000 --- a/include/clang/AST/DeclTemplate.h +++ /dev/null @@ -1,2927 +0,0 @@ -//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the C++ template declaration subclasses. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H -#define LLVM_CLANG_AST_DECLTEMPLATE_H - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Redeclarable.h" -#include "clang/AST/TemplateBase.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/TrailingObjects.h" -#include <limits> - -namespace clang { - -enum BuiltinTemplateKind : int; -class TemplateParameterList; -class TemplateDecl; -class RedeclarableTemplateDecl; -class FunctionTemplateDecl; -class ClassTemplateDecl; -class ClassTemplatePartialSpecializationDecl; -class TemplateTypeParmDecl; -class NonTypeTemplateParmDecl; -class TemplateTemplateParmDecl; -class TypeAliasTemplateDecl; -class VarTemplateDecl; -class VarTemplatePartialSpecializationDecl; - -/// \brief Stores a template parameter of any kind. -typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, - TemplateTemplateParmDecl*> TemplateParameter; - -/// \brief Stores a list of template parameters for a TemplateDecl and its -/// derived classes. -class TemplateParameterList final - : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> { - - /// The location of the 'template' keyword. - SourceLocation TemplateLoc; - - /// The locations of the '<' and '>' angle brackets. - SourceLocation LAngleLoc, RAngleLoc; - - /// The number of template parameters in this template - /// parameter list. - unsigned NumParams : 31; - - /// Whether this template parameter list contains an unexpanded parameter - /// pack. - unsigned ContainsUnexpandedParameterPack : 1; - -protected: - size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { - return NumParams; - } - - TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc); - -public: - static TemplateParameterList *Create(const ASTContext &C, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc); - - /// \brief Iterates through the template parameters in this list. - typedef NamedDecl** iterator; - - /// \brief Iterates through the template parameters in this list. - typedef NamedDecl* const* const_iterator; - - iterator begin() { return getTrailingObjects<NamedDecl *>(); } - const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); } - iterator end() { return begin() + NumParams; } - const_iterator end() const { return begin() + NumParams; } - - unsigned size() const { return NumParams; } - - ArrayRef<NamedDecl*> asArray() { - return llvm::makeArrayRef(begin(), end()); - } - ArrayRef<const NamedDecl*> asArray() const { - return llvm::makeArrayRef(begin(), size()); - } - - NamedDecl* getParam(unsigned Idx) { - assert(Idx < size() && "Template parameter index out-of-range"); - return begin()[Idx]; - } - - const NamedDecl* getParam(unsigned Idx) const { - assert(Idx < size() && "Template parameter index out-of-range"); - return begin()[Idx]; - } - - /// \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. - unsigned getMinRequiredArguments() const; - - /// \brief Get the depth of this template parameter list in the set of - /// template parameter lists. - /// - /// The first template parameter list in a declaration will have depth 0, - /// the second template parameter list will have depth 1, etc. - unsigned getDepth() const; - - /// \brief Determine whether this template parameter list contains an - /// unexpanded parameter pack. - bool containsUnexpandedParameterPack() const { - return ContainsUnexpandedParameterPack; - } - - SourceLocation getTemplateLoc() const { return TemplateLoc; } - SourceLocation getLAngleLoc() const { return LAngleLoc; } - SourceLocation getRAngleLoc() const { return RAngleLoc; } - - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(TemplateLoc, RAngleLoc); - } - - friend TrailingObjects; - template <size_t N> friend class FixedSizeTemplateParameterListStorage; -}; - -/// \brief Stores a list of template parameters for a TemplateDecl and its -/// derived classes. Suitable for creating on the stack. -template <size_t N> class FixedSizeTemplateParameterListStorage { - // This is kinda ugly: TemplateParameterList usually gets allocated - // in a block of memory with NamedDecls appended to it. Here, to get - // it stack allocated, we include the params as a separate - // variable. After allocation, the TemplateParameterList object - // treats them as part of itself. - TemplateParameterList List; - NamedDecl *Params[N]; - -public: - FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc) - : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) { - // Because we're doing an evil layout hack above, have some - // asserts, just to double-check everything is laid out like - // expected. - assert(sizeof(*this) == - TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) && - "Object layout not as expected"); - assert(this->Params == List.getTrailingObjects<NamedDecl *>() && - "Object layout not as expected"); - } - TemplateParameterList *get() { return &List; } -}; - -/// \brief A template argument list. -class TemplateArgumentList final - : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> { - /// \brief The template argument list. - const TemplateArgument *Arguments; - - /// \brief The number of template arguments in this template - /// argument list. - unsigned NumArguments; - - TemplateArgumentList(const TemplateArgumentList &Other) = delete; - void operator=(const TemplateArgumentList &Other) = delete; - - // Constructs an instance with an internal Argument list, containing - // a copy of the Args array. (Called by CreateCopy) - TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs); - -public: - /// \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), 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()), NumArguments(Other->size()) {} - - /// \brief Retrieve the template argument at a given index. - const TemplateArgument &get(unsigned Idx) const { - assert(Idx < NumArguments && "Invalid template argument index"); - return data()[Idx]; - } - - /// \brief Retrieve the template argument at a given index. - const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } - - /// \brief Produce this as an array ref. - ArrayRef<TemplateArgument> asArray() const { - return llvm::makeArrayRef(data(), size()); - } - - /// \brief Retrieve the number of template arguments in this - /// template argument list. - unsigned size() const { return NumArguments; } - - /// \brief Retrieve a pointer to the template argument list. - const TemplateArgument *data() const { return Arguments; } - - friend TrailingObjects; -}; - -void *allocateDefaultArgStorageChain(const ASTContext &C); - -/// Storage for a default argument. This is conceptually either empty, or an -/// argument value, or a pointer to a previous declaration that had a default -/// argument. -/// -/// However, this is complicated by modules: while we require all the default -/// arguments for a template to be equivalent, there may be more than one, and -/// we need to track all the originating parameters to determine if the default -/// argument is visible. -template<typename ParmDecl, typename ArgType> -class DefaultArgStorage { - /// Storage for both the value *and* another parameter from which we inherit - /// the default argument. This is used when multiple default arguments for a - /// parameter are merged together from different modules. - struct Chain { - ParmDecl *PrevDeclWithDefaultArg; - ArgType Value; - }; - static_assert(sizeof(Chain) == sizeof(void *) * 2, - "non-pointer argument type?"); - - llvm::PointerUnion3<ArgType, ParmDecl*, Chain*> ValueOrInherited; - - static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { - const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); - if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>()) - Parm = Prev; - assert(!Parm->getDefaultArgStorage() - .ValueOrInherited.template is<ParmDecl *>() && - "should only be one level of indirection"); - return Parm; - } - -public: - DefaultArgStorage() : ValueOrInherited(ArgType()) {} - - /// Determine whether there is a default argument for this parameter. - bool isSet() const { return !ValueOrInherited.isNull(); } - /// Determine whether the default argument for this parameter was inherited - /// from a previous declaration of the same entity. - bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); } - /// Get the default argument's value. This does not consider whether the - /// default argument is visible. - ArgType get() const { - const DefaultArgStorage *Storage = this; - if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>()) - Storage = &Prev->getDefaultArgStorage(); - if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>()) - return C->Value; - return Storage->ValueOrInherited.template get<ArgType>(); - } - /// Get the parameter from which we inherit the default argument, if any. - /// This is the parameter on which the default argument was actually written. - const ParmDecl *getInheritedFrom() const { - if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>()) - return D; - if (auto *C = ValueOrInherited.template dyn_cast<Chain*>()) - return C->PrevDeclWithDefaultArg; - return nullptr; - } - /// Set the default argument. - void set(ArgType Arg) { - assert(!isSet() && "default argument already set"); - ValueOrInherited = Arg; - } - /// Set that the default argument was inherited from another parameter. - void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { - assert(!isInherited() && "default argument already inherited"); - InheritedFrom = getParmOwningDefaultArg(InheritedFrom); - if (!isSet()) - ValueOrInherited = InheritedFrom; - else - ValueOrInherited = new (allocateDefaultArgStorageChain(C)) - Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()}; - } - /// Remove the default argument, even if it was inherited. - void clear() { - ValueOrInherited = ArgType(); - } -}; - -//===----------------------------------------------------------------------===// -// Kinds of Templates -//===----------------------------------------------------------------------===// - -/// \brief The base class of all kinds of template declarations (e.g., -/// class, function, etc.). -/// -/// The TemplateDecl class stores the list of template parameters and a -/// reference to the templated scoped declaration: the underlying AST node. -class TemplateDecl : public NamedDecl { - void anchor() override; -protected: - // This is probably never used. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(nullptr) {} - - // Construct a template decl with the given name and parameters. - // Used when there is not templated element (tt-params). - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(Params) {} - - // Construct a template decl with name, parameters, and templated element. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), - TemplateParams(Params) { } -public: - /// Get the list of template parameters - TemplateParameterList *getTemplateParameters() const { - return TemplateParams; - } - - /// Get the underlying, templated declaration. - NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstTemplate && K <= lastTemplate; - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(TemplateParams->getTemplateLoc(), - TemplatedDecl->getSourceRange().getEnd()); - } - -protected: - NamedDecl *TemplatedDecl; - TemplateParameterList* TemplateParams; - -public: - /// \brief Initialize the underlying templated declaration and - /// template parameters. - void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl && "TemplatedDecl already set!"); - assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl = templatedDecl; - TemplateParams = templateParams; - } -}; - -/// \brief Provides information about a function template specialization, -/// which is a FunctionDecl that has been explicitly specialization or -/// instantiated from a function template. -class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { - FunctionTemplateSpecializationInfo(FunctionDecl *FD, - FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, - const TemplateArgumentList *TemplateArgs, - const ASTTemplateArgumentListInfo *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); - - /// \brief The function template specialization that this structure - /// describes. - FunctionDecl *Function; - - /// \brief The function template from which this function template - /// specialization was generated. - /// - /// The two bits contain the top 4 values of TemplateSpecializationKind. - llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template; - - /// \brief The template arguments used to produce the function template - /// specialization from the function template. - const TemplateArgumentList *TemplateArguments; - - /// \brief The template arguments as written in the sources, if provided. - const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; - - /// \brief The point at which this function template specialization was - /// first instantiated. - SourceLocation PointOfInstantiation; - - /// \brief Retrieve the template from which this function was specialized. - FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } - - /// \brief Determine what kind of template specialization this is. - TemplateSpecializationKind getTemplateSpecializationKind() const { - return (TemplateSpecializationKind)(Template.getInt() + 1); - } - - bool isExplicitSpecialization() const { - return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; - } - - /// \brief True if this declaration is an explicit specialization, - /// explicit instantiation declaration, or explicit instantiation - /// definition. - bool isExplicitInstantiationOrSpecialization() const { - return isTemplateExplicitInstantiationOrSpecialization( - getTemplateSpecializationKind()); - } - - /// \brief Set the template specialization kind. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { - assert(TSK != TSK_Undeclared && - "Cannot encode TSK_Undeclared for a function template specialization"); - Template.setInt(TSK - 1); - } - - /// \brief Retrieve the first point of instantiation of this function - /// template specialization. - /// - /// The point of instantiation may be an invalid source location if this - /// function has yet to be instantiated. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; - } - - /// \brief Set the (first) point of instantiation of this function template - /// specialization. - void setPointOfInstantiation(SourceLocation POI) { - PointOfInstantiation = POI; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->asArray(), - Function->getASTContext()); - } - - static void - Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { - ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); - } -}; - -/// \brief Provides information a specialization of a member of a class -/// template, which may be a member function, static data member, -/// member class or member enumeration. -class MemberSpecializationInfo { - // The member declaration from which this member was instantiated, and the - // manner in which the instantiation occurred (in the lower two bits). - llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK; - - // The point at which this member was first instantiated. - SourceLocation PointOfInstantiation; - -public: - explicit - MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK, - SourceLocation POI = SourceLocation()) - : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { - assert(TSK != TSK_Undeclared && - "Cannot encode undeclared template specializations for members"); - } - - /// \brief Retrieve the member declaration from which this member was - /// instantiated. - NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); } - - /// \brief Determine what kind of template specialization this is. - TemplateSpecializationKind getTemplateSpecializationKind() const { - return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1); - } - - bool isExplicitSpecialization() const { - return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; - } - - /// \brief Set the template specialization kind. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { - assert(TSK != TSK_Undeclared && - "Cannot encode undeclared template specializations for members"); - MemberAndTSK.setInt(TSK - 1); - } - - /// \brief Retrieve the first point of instantiation of this member. - /// If the point of instantiation is an invalid location, then this member - /// has not yet been instantiated. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; - } - - /// \brief Set the first point of instantiation. - void setPointOfInstantiation(SourceLocation POI) { - PointOfInstantiation = POI; - } -}; - -/// \brief Provides information about a dependent function-template -/// specialization declaration. -/// -/// Since explicit function template specialization and instantiation -/// declarations can only appear in namespace scope, and you can only -/// specialize a member of a fully-specialized class, the only way to -/// get one of these is in a friend declaration like the following: -/// -/// \code -/// template \<class T> void foo(T); -/// template \<class T> class A { -/// friend void foo<>(T); -/// }; -/// \endcode -class DependentFunctionTemplateSpecializationInfo final - : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo, - TemplateArgumentLoc, - FunctionTemplateDecl *> { - /// The number of potential template candidates. - unsigned NumTemplates; - - /// The number of template arguments. - unsigned NumArgs; - - /// The locations of the left and right angle brackets. - SourceRange AngleLocs; - - size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { - return NumArgs; - } - size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const { - return NumTemplates; - } - - DependentFunctionTemplateSpecializationInfo( - const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); - -public: - static DependentFunctionTemplateSpecializationInfo * - Create(ASTContext &Context, const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); - - /// \brief Returns the number of function templates that this might - /// be a specialization of. - unsigned getNumTemplates() const { return NumTemplates; } - - /// \brief Returns the i'th template candidate. - FunctionTemplateDecl *getTemplate(unsigned I) const { - assert(I < getNumTemplates() && "template index out of range"); - return getTrailingObjects<FunctionTemplateDecl *>()[I]; - } - - /// \brief Returns the explicit template arguments that were given. - const TemplateArgumentLoc *getTemplateArgs() const { - return getTrailingObjects<TemplateArgumentLoc>(); - } - - /// \brief Returns the number of explicit template arguments that were given. - unsigned getNumTemplateArgs() const { return NumArgs; } - - /// \brief Returns the nth template argument. - const TemplateArgumentLoc &getTemplateArg(unsigned I) const { - assert(I < getNumTemplateArgs() && "template arg index out of range"); - return getTemplateArgs()[I]; - } - - SourceLocation getLAngleLoc() const { - return AngleLocs.getBegin(); - } - - SourceLocation getRAngleLoc() const { - return AngleLocs.getEnd(); - } - - friend TrailingObjects; -}; - -/// Declaration of a redeclarable template. -class RedeclarableTemplateDecl : public TemplateDecl, - public Redeclarable<RedeclarableTemplateDecl> -{ - typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base; - RedeclarableTemplateDecl *getNextRedeclarationImpl() override { - return getNextRedeclaration(); - } - RedeclarableTemplateDecl *getPreviousDeclImpl() override { - return getPreviousDecl(); - } - RedeclarableTemplateDecl *getMostRecentDeclImpl() override { - return getMostRecentDecl(); - } - -protected: - template <typename EntryType> struct SpecEntryTraits { - typedef EntryType DeclType; - - static DeclType *getDecl(EntryType *D) { - return D; - } - static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) { - return D->getTemplateArgs().asArray(); - } - }; - - template <typename EntryType, typename SETraits = SpecEntryTraits<EntryType>, - typename DeclType = typename SETraits::DeclType> - struct SpecIterator - : llvm::iterator_adaptor_base< - SpecIterator<EntryType, SETraits, DeclType>, - typename llvm::FoldingSetVector<EntryType>::iterator, - typename std::iterator_traits<typename llvm::FoldingSetVector< - EntryType>::iterator>::iterator_category, - DeclType *, ptrdiff_t, DeclType *, DeclType *> { - SpecIterator() {} - explicit SpecIterator( - typename llvm::FoldingSetVector<EntryType>::iterator SetIter) - : SpecIterator::iterator_adaptor_base(std::move(SetIter)) {} - - DeclType *operator*() const { - return SETraits::getDecl(&*this->I)->getMostRecentDecl(); - } - DeclType *operator->() const { return **this; } - }; - - template <typename EntryType> - static SpecIterator<EntryType> - makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) { - return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); - } - - template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* - findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, - ArrayRef<TemplateArgument> Args, void *&InsertPos); - - template <class Derived, class EntryType> - void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, - EntryType *Entry, void *InsertPos); - - struct CommonBase { - CommonBase() : InstantiatedFromMember(nullptr, false) { } - - /// \brief The template from which this was most - /// directly instantiated (or null). - /// - /// The boolean value indicates whether this template - /// was explicitly specialized. - llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> - InstantiatedFromMember; - }; - - /// \brief Pointer to the common data shared by all declarations of this - /// template. - mutable CommonBase *Common; - - /// \brief Retrieves the "common" pointer shared by all (re-)declarations of - /// the same template. Calling this routine may implicitly allocate memory - /// for the common pointer. - CommonBase *getCommonPtr() const; - - virtual CommonBase *newCommon(ASTContext &C) const = 0; - - // Construct a template decl with name, parameters, and templated element. - RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C), - Common() {} - -public: - template <class decl_type> friend class RedeclarableTemplate; - - /// \brief Retrieves the canonical declaration of this template. - RedeclarableTemplateDecl *getCanonicalDecl() override { - return getFirstDecl(); - } - const RedeclarableTemplateDecl *getCanonicalDecl() const { - return getFirstDecl(); - } - - /// \brief Determines whether this template was a specialization of a - /// member template. - /// - /// In the following example, the function template \c X<int>::f and the - /// member template \c X<int>::Inner are member specializations. - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> void f(T, U); - /// template<typename U> struct Inner; - /// }; - /// - /// template<> template<typename T> - /// void X<int>::f(int, T); - /// template<> template<typename T> - /// struct X<int>::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() const { - return getCommonPtr()->InstantiatedFromMember.getInt(); - } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); - } - - /// \brief Retrieve the member template from which this template was - /// instantiated, or NULL if this template was not instantiated from a - /// member template. - /// - /// A template is instantiated from a member template when the member - /// template itself is part of a class template (or member thereof). For - /// example, given - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> void f(T, U); - /// }; - /// - /// void test(X<int> x) { - /// x.f(1, 'a'); - /// }; - /// \endcode - /// - /// \c X<int>::f is a FunctionTemplateDecl that describes the function - /// template - /// - /// \code - /// template<typename U> void X<int>::f(int, U); - /// \endcode - /// - /// which was itself created during the instantiation of \c X<int>. Calling - /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will - /// retrieve the FunctionTemplateDecl for the original template \c f within - /// the class template \c X<T>, i.e., - /// - /// \code - /// template<typename T> - /// template<typename U> - /// void X<T>::f(T, U); - /// \endcode - RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const { - return getCommonPtr()->InstantiatedFromMember.getPointer(); - } - - void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(TD); - } - - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; - using redeclarable_base::redecls_begin; - using redeclarable_base::redecls_end; - using redeclarable_base::redecls; - using redeclarable_base::getPreviousDecl; - using redeclarable_base::getMostRecentDecl; - using redeclarable_base::isFirstDecl; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; - } - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -template <> struct RedeclarableTemplateDecl:: -SpecEntryTraits<FunctionTemplateSpecializationInfo> { - typedef FunctionDecl DeclType; - - static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) { - return I->Function; - } - static ArrayRef<TemplateArgument> - getTemplateArgs(FunctionTemplateSpecializationInfo *I) { - return I->TemplateArguments->asArray(); - } -}; - -/// Declaration of a template function. -class FunctionTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - -protected: - /// \brief Data that is common to all of the declarations of a given - /// function template. - struct Common : CommonBase { - Common() : InjectedArgs(), LazySpecializations() { } - - /// \brief The function template specializations for this function - /// template, including explicit specializations and instantiations. - llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations; - - /// \brief The set of "injected" template arguments used within this - /// function template. - /// - /// This pointer refers to the template arguments (there are as - /// many template arguments as template parameaters) for the function - /// template, and is allocated lazily, since most function templates do not - /// require the use of this information. - TemplateArgument *InjectedArgs; - - /// \brief If non-null, points to an array of specializations known only - /// by their external declaration IDs. - /// - /// The first value in the array is the number of of specializations - /// that follow. - uint32_t *LazySpecializations; - }; - - FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : RedeclarableTemplateDecl(FunctionTemplate, C, DC, L, Name, Params, - Decl) {} - - CommonBase *newCommon(ASTContext &C) const override; - - Common *getCommonPtr() const { - return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); - } - - friend class FunctionDecl; - - /// \brief Retrieve the set of function template specializations of this - /// function template. - llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & - getSpecializations() const; - - /// \brief Add a specialization of this function template. - /// - /// \param InsertPos Insert position in the FoldingSetVector, must have been - /// retrieved by an earlier call to findSpecialization(). - void addSpecialization(FunctionTemplateSpecializationInfo* Info, - void *InsertPos); - -public: - /// \brief Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations() const; - - /// Get the underlying function declaration of the template. - FunctionDecl *getTemplatedDecl() const { - return static_cast<FunctionDecl*>(TemplatedDecl); - } - - /// Returns whether this template declaration defines the primary - /// pattern. - bool isThisDeclarationADefinition() const { - return getTemplatedDecl()->isThisDeclarationADefinition(); - } - - /// \brief Return the specialization with the provided arguments if it exists, - /// otherwise return the insertion point. - FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args, - void *&InsertPos); - - FunctionTemplateDecl *getCanonicalDecl() override { - return cast<FunctionTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - const FunctionTemplateDecl *getCanonicalDecl() const { - return cast<FunctionTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - FunctionTemplateDecl *getPreviousDecl() { - return cast_or_null<FunctionTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - const FunctionTemplateDecl *getPreviousDecl() const { - return cast_or_null<FunctionTemplateDecl>( - static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl()); - } - - FunctionTemplateDecl *getMostRecentDecl() { - return cast<FunctionTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this) - ->getMostRecentDecl()); - } - const FunctionTemplateDecl *getMostRecentDecl() const { - return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl(); - } - - FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const { - return cast_or_null<FunctionTemplateDecl>( - RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); - } - - typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; - - spec_range specializations() const { - return spec_range(spec_begin(), spec_end()); - } - spec_iterator spec_begin() const { - return makeSpecIterator(getSpecializations(), false); - } - - spec_iterator spec_end() const { - return makeSpecIterator(getSpecializations(), true); - } - - /// \brief Retrieve the "injected" template arguments that correspond to the - /// template parameters of this function template. - /// - /// Although the C++ standard has no notion of the "injected" template - /// arguments for a function template, the notion is convenient when - /// we need to perform substitutions inside the definition of a function - /// template. - ArrayRef<TemplateArgument> getInjectedTemplateArgs(); - - /// \brief Create a function template node. - static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName Name, - TemplateParameterList *Params, - NamedDecl *Decl); - - /// \brief Create an empty function template node. - static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == FunctionTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -//===----------------------------------------------------------------------===// -// Kinds of Template Parameters -//===----------------------------------------------------------------------===// - -/// \brief Defines the position of a template parameter within a template -/// parameter list. -/// -/// Because template parameter can be listed -/// sequentially for out-of-line template members, each template parameter is -/// given a Depth - the nesting of template parameter scopes - and a Position - -/// the occurrence within the parameter list. -/// This class is inheritedly privately by different kinds of template -/// parameters and is not part of the Decl hierarchy. Just a facility. -class TemplateParmPosition { - TemplateParmPosition() = delete; - -protected: - TemplateParmPosition(unsigned D, unsigned P) - : Depth(D), Position(P) - { } - - // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for - // position? Maybe? - unsigned Depth; - unsigned Position; - -public: - /// Get the nesting depth of the template parameter. - unsigned getDepth() const { return Depth; } - void setDepth(unsigned D) { Depth = D; } - - /// Get the position of the template parameter within its parameter list. - unsigned getPosition() const { return Position; } - void setPosition(unsigned P) { Position = P; } - - /// Get the index of the template parameter within its parameter list. - unsigned getIndex() const { return Position; } -}; - -/// \brief Declaration of a template type parameter. -/// -/// For example, "T" in -/// \code -/// template<typename T> class vector; -/// \endcode -class TemplateTypeParmDecl : public TypeDecl { - /// \brief Whether this template type parameter was declaration with - /// the 'typename' keyword. - /// - /// If false, it was declared with the 'class' keyword. - bool Typename : 1; - - /// \brief The default template argument, if any. - typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *> - DefArgStorage; - DefArgStorage DefaultArgument; - - TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - bool Typename) - : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - DefaultArgument() { } - - /// Sema creates these on the stack during auto type deduction. - friend class Sema; - -public: - static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation KeyLoc, - SourceLocation NameLoc, - unsigned D, unsigned P, - IdentifierInfo *Id, bool Typename, - bool ParameterPack); - static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, - unsigned ID); - - /// \brief Whether this template type parameter was declared with - /// the 'typename' keyword. - /// - /// If not, it was declared with the 'class' keyword. - bool wasDeclaredWithTypename() const { return Typename; } - - const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - - /// \brief Determine whether this template parameter has a default - /// argument. - bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - - /// \brief Retrieve the default argument, if any. - QualType getDefaultArgument() const { - return DefaultArgument.get()->getType(); - } - - /// \brief Retrieves the default argument's source information, if any. - TypeSourceInfo *getDefaultArgumentInfo() const { - return DefaultArgument.get(); - } - - /// \brief Retrieves the location of the default argument declaration. - SourceLocation getDefaultArgumentLoc() const; - - /// \brief Determines whether the default argument was inherited - /// from a previous declaration of this template. - bool defaultArgumentWasInherited() const { - return DefaultArgument.isInherited(); - } - - /// \brief Set the default argument for this template parameter. - void setDefaultArgument(TypeSourceInfo *DefArg) { - DefaultArgument.set(DefArg); - } - /// \brief Set that this default argument was inherited from another - /// parameter. - void setInheritedDefaultArgument(const ASTContext &C, - TemplateTypeParmDecl *Prev) { - DefaultArgument.setInherited(C, Prev); - } - - /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { - DefaultArgument.clear(); - } - - /// \brief Set whether this template type parameter was declared with - /// the 'typename' or 'class' keyword. - void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - - /// \brief Retrieve the depth of the template parameter. - unsigned getDepth() const; - - /// \brief Retrieve the index of the template parameter. - unsigned getIndex() const; - - /// \brief Returns whether this is a parameter pack. - bool isParameterPack() const; - - SourceRange getSourceRange() const override LLVM_READONLY; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == TemplateTypeParm; } -}; - -/// NonTypeTemplateParmDecl - Declares a non-type template parameter, -/// e.g., "Size" in -/// @code -/// template<int Size> class array { }; -/// @endcode -class NonTypeTemplateParmDecl final - : public DeclaratorDecl, - protected TemplateParmPosition, - private llvm::TrailingObjects<NonTypeTemplateParmDecl, - std::pair<QualType, TypeSourceInfo *>> { - /// \brief The default template argument, if any, and whether or not - /// it was inherited. - typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage; - DefArgStorage DefaultArgument; - - // 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; - - size_t numTrailingObjects( - OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const { - return NumExpandedTypes; - } - - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, unsigned D, unsigned P, - IdentifierInfo *Id, QualType T, - bool ParameterPack, TypeSourceInfo *TInfo) - : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), ParameterPack(ParameterPack), - ExpandedParameterPack(false), NumExpandedTypes(0) - { } - - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, unsigned D, unsigned P, - IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, - unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos); - - friend class ASTDeclReader; - friend TrailingObjects; - -public: - static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, - QualType T, bool ParameterPack, TypeSourceInfo *TInfo); - - static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos); - - static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID); - static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID, - unsigned NumExpandedTypes); - - using TemplateParmPosition::getDepth; - using TemplateParmPosition::setDepth; - using TemplateParmPosition::getPosition; - using TemplateParmPosition::setPosition; - using TemplateParmPosition::getIndex; - - SourceRange getSourceRange() const override LLVM_READONLY; - - const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - - /// \brief Determine whether this template parameter has a default - /// argument. - bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - - /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument.get(); } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; - - /// \brief Determines whether the default argument was inherited - /// from a previous declaration of this template. - bool defaultArgumentWasInherited() const { - return DefaultArgument.isInherited(); - } - - /// \brief Set the default argument for this template parameter, and - /// whether that default argument was inherited from another - /// declaration. - void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } - void setInheritedDefaultArgument(const ASTContext &C, - NonTypeTemplateParmDecl *Parm) { - DefaultArgument.setInherited(C, Parm); - } - - /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { DefaultArgument.clear(); } - - /// \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 pack is a pack expansion. - /// - /// A non-type template parameter pack is a pack expansion if its type - /// contains an unexpanded parameter pack. In this case, we will have - /// built a PackExpansionType wrapping the type. - bool isPackExpansion() const { - return ParameterPack && getType()->getAs<PackExpansionType>(); - } - - /// \brief Whether this parameter is a non-type template parameter pack - /// that has a known list of 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"); - auto TypesAndInfos = - getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); - return TypesAndInfos[I].first; - } - - /// \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"); - auto TypesAndInfos = - getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); - return TypesAndInfos[I].second; - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } -}; - -/// TemplateTemplateParmDecl - Declares a template template parameter, -/// e.g., "T" in -/// @code -/// template <template <typename> class T> class container { }; -/// @endcode -/// A template template parameter is a TemplateDecl because it defines the -/// name of a template and the template parameters allowable for substitution. -class TemplateTemplateParmDecl final - : public TemplateDecl, - protected TemplateParmPosition, - private llvm::TrailingObjects<TemplateTemplateParmDecl, - TemplateParameterList *> { - void anchor() override; - - /// \brief The default template argument, if any. - typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *> - DefArgStorage; - DefArgStorage DefaultArgument; - - /// \brief Whether this parameter is a parameter pack. - bool ParameterPack; - - /// \brief Whether this template template parameter is an "expanded" - /// parameter pack, meaning that it is a pack expansion and we - /// already know the set of template parameters that expansion expands to. - bool ExpandedParameterPack; - - /// \brief The number of parameters in an expanded parameter pack. - unsigned NumExpandedParams; - - TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, - unsigned D, unsigned P, bool ParameterPack, - IdentifierInfo *Id, TemplateParameterList *Params) - : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), ParameterPack(ParameterPack), - ExpandedParameterPack(false), NumExpandedParams(0) - { } - - TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, - unsigned D, unsigned P, - IdentifierInfo *Id, TemplateParameterList *Params, - unsigned NumExpansions, - TemplateParameterList * const *Expansions); - -public: - static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, - unsigned P, bool ParameterPack, - IdentifierInfo *Id, - TemplateParameterList *Params); - static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, - unsigned P, - IdentifierInfo *Id, - TemplateParameterList *Params, - ArrayRef<TemplateParameterList *> Expansions); - - static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID); - static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID, - unsigned NumExpansions); - - 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 Whether this parameter pack is a pack expansion. - /// - /// A template template parameter pack is a pack expansion if its template - /// parameter list contains an unexpanded parameter pack. - bool isPackExpansion() const { - return ParameterPack && - getTemplateParameters()->containsUnexpandedParameterPack(); - } - - /// \brief Whether this parameter is a template template parameter pack that - /// has a known list of different template parameter lists at different - /// positions. - /// - /// A parameter pack is an expanded parameter pack when the original parameter - /// pack's template parameter list was itself a pack expansion, and that - /// expansion has already been expanded. For exampe, given: - /// - /// \code - /// template<typename...Types> struct Outer { - /// template<template<Types> class...Templates> struct Inner; - /// }; - /// \endcode - /// - /// The parameter pack \c Templates is a pack expansion, which expands the - /// pack \c Types. When \c Types is supplied with template arguments by - /// instantiating \c Outer, the instantiation of \c Templates is an expanded - /// parameter pack. - bool isExpandedParameterPack() const { return ExpandedParameterPack; } - - /// \brief Retrieves the number of expansion template parameters in - /// an expanded parameter pack. - unsigned getNumExpansionTemplateParameters() const { - assert(ExpandedParameterPack && "Not an expansion parameter pack"); - return NumExpandedParams; - } - - /// \brief Retrieve a particular expansion type within an expanded parameter - /// pack. - TemplateParameterList *getExpansionTemplateParameters(unsigned I) const { - assert(I < NumExpandedParams && "Out-of-range expansion type index"); - return getTrailingObjects<TemplateParameterList *>()[I]; - } - - const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - - /// \brief Determine whether this template parameter has a default - /// argument. - bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - - /// \brief Retrieve the default argument, if any. - const TemplateArgumentLoc &getDefaultArgument() const { - static const TemplateArgumentLoc None; - return DefaultArgument.isSet() ? *DefaultArgument.get() : None; - } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; - - /// \brief Determines whether the default argument was inherited - /// from a previous declaration of this template. - bool defaultArgumentWasInherited() const { - return DefaultArgument.isInherited(); - } - - /// \brief Set the default argument for this template parameter, and - /// whether that default argument was inherited from another - /// declaration. - void setDefaultArgument(const ASTContext &C, - const TemplateArgumentLoc &DefArg); - void setInheritedDefaultArgument(const ASTContext &C, - TemplateTemplateParmDecl *Prev) { - DefaultArgument.setInherited(C, Prev); - } - - /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { DefaultArgument.clear(); } - - SourceRange getSourceRange() const override LLVM_READONLY { - SourceLocation End = getLocation(); - if (hasDefaultArgument() && !defaultArgumentWasInherited()) - End = getDefaultArgument().getSourceRange().getEnd(); - return SourceRange(getTemplateParameters()->getTemplateLoc(), End); - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == TemplateTemplateParm; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; -}; - -/// \brief Represents the builtin template declaration which is used to -/// implement __make_integer_seq. It serves no real purpose beyond existing as -/// a place to hold template parameters. -class BuiltinTemplateDecl : public TemplateDecl { - void anchor() override; - - BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, - DeclarationName Name, BuiltinTemplateKind BTK); - - BuiltinTemplateKind BTK; - -public: - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == BuiltinTemplate; } - - static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC, - DeclarationName Name, - BuiltinTemplateKind BTK) { - return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK); - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(); - } - - BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } -}; - -/// \brief Represents a class template specialization, which refers to -/// a class template with a given set of template arguments. -/// -/// Class template specializations represent both explicit -/// specialization of class templates, as in the example below, and -/// implicit instantiations of class templates. -/// -/// \code -/// template<typename T> class array; -/// -/// template<> -/// class array<bool> { }; // class template specialization array<bool> -/// \endcode -class ClassTemplateSpecializationDecl - : public CXXRecordDecl, public llvm::FoldingSetNode { - - /// \brief Structure that stores information about a class template - /// specialization that was instantiated from a class template partial - /// specialization. - struct SpecializedPartialSpecialization { - /// \brief The class template partial specialization from which this - /// class template specialization was instantiated. - ClassTemplatePartialSpecializationDecl *PartialSpecialization; - - /// \brief The template argument list deduced for the class template - /// partial specialization itself. - const TemplateArgumentList *TemplateArgs; - }; - - /// \brief The template that this specialization specializes - llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> - SpecializedTemplate; - - /// \brief Further info for explicit template specialization/instantiation. - struct ExplicitSpecializationInfo { - /// \brief The type-as-written. - TypeSourceInfo *TypeAsWritten; - /// \brief The location of the extern keyword. - SourceLocation ExternLoc; - /// \brief The location of the template keyword. - SourceLocation TemplateKeywordLoc; - - ExplicitSpecializationInfo() - : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} - }; - - /// \brief Further info for explicit template specialization/instantiation. - /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo; - - /// \brief The template arguments used to describe this specialization. - const TemplateArgumentList *TemplateArgs; - - /// \brief The point where this template was instantiated (if any) - SourceLocation PointOfInstantiation; - - /// \brief The kind of specialization this declaration refers to. - /// Really a value of type TemplateSpecializationKind. - unsigned SpecializationKind : 3; - -protected: - ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, - DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, - ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, - ClassTemplateSpecializationDecl *PrevDecl); - - explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); - -public: - static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, - ClassTemplateSpecializationDecl *PrevDecl); - static ClassTemplateSpecializationDecl * - CreateDeserialized(ASTContext &C, unsigned ID); - - void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, - bool Qualified) const override; - - // FIXME: This is broken. CXXRecordDecl::getMostRecentDecl() returns a - // different "most recent" declaration from this function for the same - // declaration, because we don't override getMostRecentDeclImpl(). But - // it's not clear that we should override that, because the most recent - // declaration as a CXXRecordDecl sometimes is the injected-class-name. - ClassTemplateSpecializationDecl *getMostRecentDecl() { - CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>( - this)->getMostRecentDecl(); - while (!isa<ClassTemplateSpecializationDecl>(Recent)) { - // FIXME: Does injected class name need to be in the redeclarations chain? - assert(Recent->isInjectedClassName() && Recent->getPreviousDecl()); - Recent = Recent->getPreviousDecl(); - } - return cast<ClassTemplateSpecializationDecl>(Recent); - } - - /// \brief Retrieve the template that this specialization specializes. - ClassTemplateDecl *getSpecializedTemplate() const; - - /// \brief Retrieve the template arguments of the class template - /// specialization. - const TemplateArgumentList &getTemplateArgs() const { - return *TemplateArgs; - } - - /// \brief Determine the kind of specialization that this - /// declaration represents. - TemplateSpecializationKind getSpecializationKind() const { - return static_cast<TemplateSpecializationKind>(SpecializationKind); - } - - bool isExplicitSpecialization() const { - return getSpecializationKind() == TSK_ExplicitSpecialization; - } - - /// \brief True if this declaration is an explicit specialization, - /// explicit instantiation declaration, or explicit instantiation - /// definition. - bool isExplicitInstantiationOrSpecialization() const { - return isTemplateExplicitInstantiationOrSpecialization( - getTemplateSpecializationKind()); - } - - void setSpecializationKind(TemplateSpecializationKind TSK) { - SpecializationKind = TSK; - } - - /// \brief Get the point of instantiation (if any), or null if none. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; - } - - void setPointOfInstantiation(SourceLocation Loc) { - assert(Loc.isValid() && "point of instantiation must be valid!"); - PointOfInstantiation = Loc; - } - - /// \brief If this class template specialization is an instantiation of - /// a template (rather than an explicit specialization), return the - /// class template or class template partial specialization from which it - /// was instantiated. - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> - getInstantiatedFrom() const { - if (!isTemplateInstantiation(getSpecializationKind())) - return llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *>(); - - return getSpecializedTemplateOrPartial(); - } - - /// \brief Retrieve the class template or class template partial - /// specialization which was specialized by this. - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> - getSpecializedTemplateOrPartial() const { - if (SpecializedPartialSpecialization *PartialSpec - = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) - return PartialSpec->PartialSpecialization; - - return SpecializedTemplate.get<ClassTemplateDecl*>(); - } - - /// \brief Retrieve the set of template arguments that should be used - /// to instantiate members of the class template or class template partial - /// specialization from which this class template specialization was - /// instantiated. - /// - /// \returns For a class template specialization instantiated from the primary - /// template, this function will return the same template arguments as - /// getTemplateArgs(). For a class template specialization instantiated from - /// a class template partial specialization, this function will return the - /// deduced template arguments for the class template partial specialization - /// itself. - const TemplateArgumentList &getTemplateInstantiationArgs() const { - if (SpecializedPartialSpecialization *PartialSpec - = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) - return *PartialSpec->TemplateArgs; - - return getTemplateArgs(); - } - - /// \brief Note that this class template specialization is actually an - /// instantiation of the given class template partial specialization whose - /// template arguments have been deduced. - void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, - const TemplateArgumentList *TemplateArgs) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && - "Already set to a class template partial specialization!"); - SpecializedPartialSpecialization *PS - = new (getASTContext()) SpecializedPartialSpecialization(); - PS->PartialSpecialization = PartialSpec; - PS->TemplateArgs = TemplateArgs; - SpecializedTemplate = PS; - } - - /// \brief Note that this class template specialization is an instantiation - /// of the given class template. - void setInstantiationOf(ClassTemplateDecl *TemplDecl) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && - "Previously set to a class template partial specialization!"); - SpecializedTemplate = TemplDecl; - } - - /// \brief Sets the type of this specialization as it was written by - /// the user. This will be a class template specialization type. - void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = T; - } - /// \brief Gets the type of this specialization as it was written by - /// the user, if it was so written. - TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; - } - - /// \brief Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); - } - /// \brief Sets the location of the extern keyword. - void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->ExternLoc = Loc; - } - - /// \brief Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TemplateKeywordLoc = Loc; - } - /// \brief Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); - } - - SourceRange getSourceRange() const override LLVM_READONLY; - - void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs->asArray(), getASTContext()); - } - - static void - Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { - ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstClassTemplateSpecialization && - K <= lastClassTemplateSpecialization; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -class ClassTemplatePartialSpecializationDecl - : public ClassTemplateSpecializationDecl { - void anchor() override; - - /// \brief The list of template parameters - TemplateParameterList* TemplateParams; - - /// \brief The source info for the template arguments as written. - /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten; - - /// \brief The class template partial specialization from which this - /// class template partial specialization was instantiated. - /// - /// The boolean value will be true to indicate that this class template - /// partial specialization was specialized at this level. - llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> - InstantiatedFromMember; - - ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ClassTemplatePartialSpecializationDecl *PrevDecl); - - ClassTemplatePartialSpecializationDecl(ASTContext &C) - : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), - TemplateParams(nullptr), ArgsAsWritten(nullptr), - InstantiatedFromMember(nullptr, false) {} - -public: - static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, - const TemplateArgumentListInfo &ArgInfos, - QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl); - - static ClassTemplatePartialSpecializationDecl * - CreateDeserialized(ASTContext &C, unsigned ID); - - ClassTemplatePartialSpecializationDecl *getMostRecentDecl() { - return cast<ClassTemplatePartialSpecializationDecl>( - static_cast<ClassTemplateSpecializationDecl *>( - this)->getMostRecentDecl()); - } - - /// Get the list of template parameters - TemplateParameterList *getTemplateParameters() const { - return TemplateParams; - } - - /// Get the template arguments as written. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return ArgsAsWritten; - } - - /// \brief Retrieve the member class template partial specialization from - /// which this particular class template partial specialization was - /// instantiated. - /// - /// \code - /// template<typename T> - /// struct Outer { - /// template<typename U> struct Inner; - /// template<typename U> struct Inner<U*> { }; // #1 - /// }; - /// - /// Outer<float>::Inner<int*> ii; - /// \endcode - /// - /// In this example, the instantiation of \c Outer<float>::Inner<int*> will - /// end up instantiating the partial specialization - /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class - /// template partial specialization \c Outer<T>::Inner<U*>. Given - /// \c Outer<float>::Inner<U*>, this function would return - /// \c Outer<T>::Inner<U*>. - ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { - const ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); - return First->InstantiatedFromMember.getPointer(); - } - - void setInstantiatedFromMember( - ClassTemplatePartialSpecializationDecl *PartialSpec) { - ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); - First->InstantiatedFromMember.setPointer(PartialSpec); - } - - /// \brief Determines whether this class template partial specialization - /// template was a specialization of a member partial specialization. - /// - /// In the following example, the member template partial specialization - /// \c X<int>::Inner<T*> is a member specialization. - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> struct Inner; - /// template<typename U> struct Inner<U*>; - /// }; - /// - /// template<> template<typename T> - /// struct X<int>::Inner<T*> { /* ... */ }; - /// \endcode - bool isMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); - return First->InstantiatedFromMember.getInt(); - } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); - assert(First->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - return First->InstantiatedFromMember.setInt(true); - } - - /// Retrieves the injected specialization type for this partial - /// specialization. This is not the same as the type-decl-type for - /// this partial specialization, which is an InjectedClassNameType. - QualType getInjectedSpecializationType() const { - assert(getTypeForDecl() && "partial specialization has no type set!"); - return cast<InjectedClassNameType>(getTypeForDecl()) - ->getInjectedSpecializationType(); - } - - // FIXME: Add Profile support! - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K == ClassTemplatePartialSpecialization; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// Declaration of a class template. -class ClassTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - -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::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations; - - /// \brief The class template partial specializations for this class - /// template. - llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> - PartialSpecializations; - - /// \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 only 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 Retrieve the set of specializations of this class template. - llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & - getSpecializations() const; - - /// \brief Retrieve the set of partial specializations of this class - /// template. - llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & - getPartialSpecializations(); - - ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {} - - CommonBase *newCommon(ASTContext &C) const override; - - Common *getCommonPtr() const { - return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); - } - -public: - /// \brief Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations() const; - - /// \brief Get the underlying class declarations of the template. - CXXRecordDecl *getTemplatedDecl() const { - return static_cast<CXXRecordDecl *>(TemplatedDecl); - } - - /// \brief Returns whether this template declaration defines the primary - /// class pattern. - bool isThisDeclarationADefinition() const { - return getTemplatedDecl()->isThisDeclarationADefinition(); - } - - /// \brief Create a class template node. - static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName Name, - TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl); - - /// \brief Create an empty class template node. - static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// \brief Return the specialization with the provided arguments if it exists, - /// otherwise return the insertion point. - ClassTemplateSpecializationDecl * - findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - - /// \brief Insert the specified specialization knowing that it is not already - /// in. InsertPos must be obtained from findSpecialization. - void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); - - ClassTemplateDecl *getCanonicalDecl() override { - return cast<ClassTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - const ClassTemplateDecl *getCanonicalDecl() const { - return cast<ClassTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. - ClassTemplateDecl *getPreviousDecl() { - return cast_or_null<ClassTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); - } - - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. - const ClassTemplateDecl *getPreviousDecl() const { - return cast_or_null<ClassTemplateDecl>( - static_cast<const RedeclarableTemplateDecl *>( - this)->getPreviousDecl()); - } - - ClassTemplateDecl *getMostRecentDecl() { - return cast<ClassTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl()); - } - const ClassTemplateDecl *getMostRecentDecl() const { - return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl(); - } - - ClassTemplateDecl *getInstantiatedFromMemberTemplate() const { - return cast_or_null<ClassTemplateDecl>( - RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); - } - - /// \brief Return the partial specialization with the provided arguments if it - /// exists, otherwise return the insertion point. - ClassTemplatePartialSpecializationDecl * - findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - - /// \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); - - /// \brief Retrieve the partial specializations as an ordered list. - void getPartialSpecializations( - SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); - - /// \brief Find a class template partial specialization with the given - /// type T. - /// - /// \param T a dependent type that names a specialization of this class - /// template. - /// - /// \returns the class template partial specialization that exactly matches - /// the type \p T, or NULL if no such partial specialization exists. - ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); - - /// \brief Find a class template partial specialization which was instantiated - /// from the given member partial specialization. - /// - /// \param D a member class template partial specialization. - /// - /// \returns the class template partial specialization which was instantiated - /// from the given member partial specialization, or NULL if no such partial - /// specialization exists. - ClassTemplatePartialSpecializationDecl * - findPartialSpecInstantiatedFromMember( - ClassTemplatePartialSpecializationDecl *D); - - /// \brief Retrieve the template specialization type of the - /// injected-class-name for this class template. - /// - /// The injected-class-name for a class template \c X is \c - /// X<template-args>, where \c template-args is formed from the - /// template arguments that correspond to the template parameters of - /// \c X. For example: - /// - /// \code - /// template<typename T, int N> - /// struct array { - /// typedef array this_type; // "array" is equivalent to "array<T, N>" - /// }; - /// \endcode - QualType getInjectedClassNameSpecialization(); - - typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; - - spec_range specializations() const { - return spec_range(spec_begin(), spec_end()); - } - - spec_iterator spec_begin() const { - return makeSpecIterator(getSpecializations(), false); - } - - spec_iterator spec_end() const { - return makeSpecIterator(getSpecializations(), true); - } - - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ClassTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Declaration of a friend template. -/// -/// For example: -/// \code -/// template \<typename T> class A { -/// friend class MyVector<T>; // not a friend template -/// template \<typename U> friend class B; // not a friend template -/// template \<typename U> friend class Foo<T>::Nested; // friend template -/// }; -/// \endcode -/// -/// \note This class is not currently in use. All of the above -/// will yield a FriendDecl, not a FriendTemplateDecl. -class FriendTemplateDecl : public Decl { - virtual void anchor(); -public: - typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; - -private: - // The number of template parameters; always non-zero. - unsigned NumParams; - - // The parameter list. - TemplateParameterList **Params; - - // The declaration that's a friend of this class. - FriendUnion Friend; - - // Location of the 'friend' specifier. - SourceLocation FriendLoc; - - - FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, - unsigned NParams, - TemplateParameterList **Params, - FriendUnion Friend, - SourceLocation FriendLoc) - : Decl(Decl::FriendTemplate, DC, Loc), - NumParams(NParams), - Params(Params), - Friend(Friend), - FriendLoc(FriendLoc) - {} - - FriendTemplateDecl(EmptyShell Empty) - : Decl(Decl::FriendTemplate, Empty), - NumParams(0), - Params(nullptr) - {} - -public: - static FriendTemplateDecl *Create(ASTContext &Context, - DeclContext *DC, SourceLocation Loc, - unsigned NParams, - TemplateParameterList **Params, - FriendUnion Friend, - SourceLocation FriendLoc); - - static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// If this friend declaration names a templated type (or - /// a dependent member type of a templated type), return that - /// type; otherwise return null. - TypeSourceInfo *getFriendType() const { - return Friend.dyn_cast<TypeSourceInfo*>(); - } - - /// If this friend declaration names a templated function (or - /// a member function of a templated type), return that type; - /// otherwise return null. - NamedDecl *getFriendDecl() const { - return Friend.dyn_cast<NamedDecl*>(); - } - - /// \brief Retrieves the location of the 'friend' keyword. - SourceLocation getFriendLoc() const { - return FriendLoc; - } - - TemplateParameterList *getTemplateParameterList(unsigned i) const { - assert(i <= NumParams); - return Params[i]; - } - - unsigned getNumTemplateParameters() const { - return NumParams; - } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } - - friend class ASTDeclReader; -}; - -/// \brief Declaration of an alias template. -/// -/// For example: -/// \code -/// template \<typename T> using V = std::map<T*, int, MyCompare<T>>; -/// \endcode -class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - -protected: - typedef CommonBase Common; - - TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : RedeclarableTemplateDecl(TypeAliasTemplate, C, DC, L, Name, Params, - Decl) {} - - CommonBase *newCommon(ASTContext &C) const override; - - Common *getCommonPtr() { - return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); - } - -public: - /// Get the underlying function declaration of the template. - TypeAliasDecl *getTemplatedDecl() const { - return static_cast<TypeAliasDecl*>(TemplatedDecl); - } - - - TypeAliasTemplateDecl *getCanonicalDecl() override { - return cast<TypeAliasTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - const TypeAliasTemplateDecl *getCanonicalDecl() const { - return cast<TypeAliasTemplateDecl>( - RedeclarableTemplateDecl::getCanonicalDecl()); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - TypeAliasTemplateDecl *getPreviousDecl() { - return cast_or_null<TypeAliasTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - const TypeAliasTemplateDecl *getPreviousDecl() const { - return cast_or_null<TypeAliasTemplateDecl>( - static_cast<const RedeclarableTemplateDecl *>( - this)->getPreviousDecl()); - } - - TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const { - return cast_or_null<TypeAliasTemplateDecl>( - RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); - } - - - /// \brief Create a function template node. - static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName Name, - TemplateParameterList *Params, - NamedDecl *Decl); - - /// \brief Create an empty alias template node. - static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == TypeAliasTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Declaration of a function specialization at template class scope. -/// -/// This is a non-standard extension needed to support MSVC. -/// -/// For example: -/// \code -/// template <class T> -/// class A { -/// template <class U> void foo(U a) { } -/// template<> void foo(int a) { } -/// } -/// \endcode -/// -/// "template<> foo(int a)" will be saved in Specialization as a normal -/// CXXMethodDecl. Then during an instantiation of class A, it will be -/// transformed into an actual function specialization. -class ClassScopeFunctionSpecializationDecl : public Decl { - virtual void anchor(); - - ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD, bool Args, - TemplateArgumentListInfo TemplArgs) - : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD), HasExplicitTemplateArgs(Args), - TemplateArgs(TemplArgs) {} - - ClassScopeFunctionSpecializationDecl(EmptyShell Empty) - : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} - - CXXMethodDecl *Specialization; - bool HasExplicitTemplateArgs; - TemplateArgumentListInfo TemplateArgs; - -public: - CXXMethodDecl *getSpecialization() const { return Specialization; } - bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } - const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; } - - static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C, - DeclContext *DC, - SourceLocation Loc, - CXXMethodDecl *FD, - bool HasExplicitTemplateArgs, - TemplateArgumentListInfo TemplateArgs) { - return new (C, DC) ClassScopeFunctionSpecializationDecl( - DC, Loc, FD, HasExplicitTemplateArgs, TemplateArgs); - } - - static ClassScopeFunctionSpecializationDecl * - CreateDeserialized(ASTContext &Context, unsigned ID); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K == Decl::ClassScopeFunctionSpecialization; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// Implementation of inline functions that require the template declarations -inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) - : Function(FTD) { } - -/// \brief Represents a variable template specialization, which refers to -/// a variable template with a given set of template arguments. -/// -/// Variable template specializations represent both explicit -/// specializations of variable templates, as in the example below, and -/// implicit instantiations of variable templates. -/// -/// \code -/// template<typename T> constexpr T pi = T(3.1415926535897932385); -/// -/// template<> -/// constexpr float pi<float>; // variable template specialization pi<float> -/// \endcode -class VarTemplateSpecializationDecl : public VarDecl, - public llvm::FoldingSetNode { - - /// \brief Structure that stores information about a variable template - /// specialization that was instantiated from a variable template partial - /// specialization. - struct SpecializedPartialSpecialization { - /// \brief The variable template partial specialization from which this - /// variable template specialization was instantiated. - VarTemplatePartialSpecializationDecl *PartialSpecialization; - - /// \brief The template argument list deduced for the variable template - /// partial specialization itself. - const TemplateArgumentList *TemplateArgs; - }; - - /// \brief The template that this specialization specializes. - llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *> - SpecializedTemplate; - - /// \brief Further info for explicit template specialization/instantiation. - struct ExplicitSpecializationInfo { - /// \brief The type-as-written. - TypeSourceInfo *TypeAsWritten; - /// \brief The location of the extern keyword. - SourceLocation ExternLoc; - /// \brief The location of the template keyword. - SourceLocation TemplateKeywordLoc; - - ExplicitSpecializationInfo() - : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} - }; - - /// \brief Further info for explicit template specialization/instantiation. - /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo; - - /// \brief The template arguments used to describe this specialization. - const TemplateArgumentList *TemplateArgs; - TemplateArgumentListInfo TemplateArgsInfo; - - /// \brief The point where this template was instantiated (if any). - SourceLocation PointOfInstantiation; - - /// \brief The kind of specialization this declaration refers to. - /// Really a value of type TemplateSpecializationKind. - unsigned SpecializationKind : 3; - -protected: - VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - VarTemplateDecl *SpecializedTemplate, - QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, - unsigned NumArgs); - - explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context); - -public: - static VarTemplateSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, - unsigned NumArgs); - static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, - unsigned ID); - - void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, - bool Qualified) const override; - - VarTemplateSpecializationDecl *getMostRecentDecl() { - VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl(); - return cast<VarTemplateSpecializationDecl>(Recent); - } - - /// \brief Retrieve the template that this specialization specializes. - VarTemplateDecl *getSpecializedTemplate() const; - - /// \brief Retrieve the template arguments of the variable template - /// specialization. - const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } - - // TODO: Always set this when creating the new specialization? - void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); - - const TemplateArgumentListInfo &getTemplateArgsInfo() const { - return TemplateArgsInfo; - } - - /// \brief Determine the kind of specialization that this - /// declaration represents. - TemplateSpecializationKind getSpecializationKind() const { - return static_cast<TemplateSpecializationKind>(SpecializationKind); - } - - bool isExplicitSpecialization() const { - return getSpecializationKind() == TSK_ExplicitSpecialization; - } - - /// \brief True if this declaration is an explicit specialization, - /// explicit instantiation declaration, or explicit instantiation - /// definition. - bool isExplicitInstantiationOrSpecialization() const { - return isTemplateExplicitInstantiationOrSpecialization( - getTemplateSpecializationKind()); - } - - void setSpecializationKind(TemplateSpecializationKind TSK) { - SpecializationKind = TSK; - } - - /// \brief Get the point of instantiation (if any), or null if none. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; - } - - void setPointOfInstantiation(SourceLocation Loc) { - assert(Loc.isValid() && "point of instantiation must be valid!"); - PointOfInstantiation = Loc; - } - - /// \brief If this variable template specialization is an instantiation of - /// a template (rather than an explicit specialization), return the - /// variable template or variable template partial specialization from which - /// it was instantiated. - llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> - getInstantiatedFrom() const { - if (getSpecializationKind() != TSK_ImplicitInstantiation && - getSpecializationKind() != TSK_ExplicitInstantiationDefinition && - getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) - return llvm::PointerUnion<VarTemplateDecl *, - VarTemplatePartialSpecializationDecl *>(); - - if (SpecializedPartialSpecialization *PartialSpec = - SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) - return PartialSpec->PartialSpecialization; - - return SpecializedTemplate.get<VarTemplateDecl *>(); - } - - /// \brief Retrieve the variable template or variable template partial - /// specialization which was specialized by this. - llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> - getSpecializedTemplateOrPartial() const { - if (SpecializedPartialSpecialization *PartialSpec = - SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) - return PartialSpec->PartialSpecialization; - - return SpecializedTemplate.get<VarTemplateDecl *>(); - } - - /// \brief Retrieve the set of template arguments that should be used - /// to instantiate the initializer of the variable template or variable - /// template partial specialization from which this variable template - /// specialization was instantiated. - /// - /// \returns For a variable template specialization instantiated from the - /// primary template, this function will return the same template arguments - /// as getTemplateArgs(). For a variable template specialization instantiated - /// from a variable template partial specialization, this function will the - /// return deduced template arguments for the variable template partial - /// specialization itself. - const TemplateArgumentList &getTemplateInstantiationArgs() const { - if (SpecializedPartialSpecialization *PartialSpec = - SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) - return *PartialSpec->TemplateArgs; - - return getTemplateArgs(); - } - - /// \brief Note that this variable template specialization is actually an - /// instantiation of the given variable template partial specialization whose - /// template arguments have been deduced. - void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec, - const TemplateArgumentList *TemplateArgs) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && - "Already set to a variable template partial specialization!"); - SpecializedPartialSpecialization *PS = - new (getASTContext()) SpecializedPartialSpecialization(); - PS->PartialSpecialization = PartialSpec; - PS->TemplateArgs = TemplateArgs; - SpecializedTemplate = PS; - } - - /// \brief Note that this variable template specialization is an instantiation - /// of the given variable template. - void setInstantiationOf(VarTemplateDecl *TemplDecl) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && - "Previously set to a variable template partial specialization!"); - SpecializedTemplate = TemplDecl; - } - - /// \brief Sets the type of this specialization as it was written by - /// the user. - void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = T; - } - /// \brief Gets the type of this specialization as it was written by - /// the user, if it was so written. - TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; - } - - /// \brief Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); - } - /// \brief Sets the location of the extern keyword. - void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->ExternLoc = Loc; - } - - /// \brief Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TemplateKeywordLoc = Loc; - } - /// \brief Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); - } - - void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs->asArray(), getASTContext()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, - ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { - ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K >= firstVarTemplateSpecialization && - K <= lastVarTemplateSpecialization; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -class VarTemplatePartialSpecializationDecl - : public VarTemplateSpecializationDecl { - void anchor() override; - - /// \brief The list of template parameters - TemplateParameterList *TemplateParams; - - /// \brief The source info for the template arguments as written. - /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten; - - /// \brief The variable template partial specialization from which this - /// variable template partial specialization was instantiated. - /// - /// The boolean value will be true to indicate that this variable template - /// partial specialization was specialized at this level. - llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool> - InstantiatedFromMember; - - VarTemplatePartialSpecializationDecl( - ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, TemplateParameterList *Params, - VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, unsigned NumArgs, - const ASTTemplateArgumentListInfo *ArgInfos); - - VarTemplatePartialSpecializationDecl(ASTContext &Context) - : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context), - TemplateParams(nullptr), ArgsAsWritten(nullptr), - InstantiatedFromMember(nullptr, false) {} - -public: - static VarTemplatePartialSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, TemplateParameterList *Params, - VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, - unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos); - - static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C, - unsigned ID); - - VarTemplatePartialSpecializationDecl *getMostRecentDecl() { - return cast<VarTemplatePartialSpecializationDecl>( - static_cast<VarTemplateSpecializationDecl *>( - this)->getMostRecentDecl()); - } - - /// Get the list of template parameters - TemplateParameterList *getTemplateParameters() const { - return TemplateParams; - } - - /// Get the template arguments as written. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return ArgsAsWritten; - } - - /// \brief Retrieve the member variable template partial specialization from - /// which this particular variable template partial specialization was - /// instantiated. - /// - /// \code - /// template<typename T> - /// struct Outer { - /// template<typename U> U Inner; - /// template<typename U> U* Inner<U*> = (U*)(0); // #1 - /// }; - /// - /// template int* Outer<float>::Inner<int*>; - /// \endcode - /// - /// In this example, the instantiation of \c Outer<float>::Inner<int*> will - /// end up instantiating the partial specialization - /// \c Outer<float>::Inner<U*>, which itself was instantiated from the - /// variable template partial specialization \c Outer<T>::Inner<U*>. Given - /// \c Outer<float>::Inner<U*>, this function would return - /// \c Outer<T>::Inner<U*>. - VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { - const VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); - return First->InstantiatedFromMember.getPointer(); - } - - void - setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) { - VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); - First->InstantiatedFromMember.setPointer(PartialSpec); - } - - /// \brief Determines whether this variable template partial specialization - /// was a specialization of a member partial specialization. - /// - /// In the following example, the member template partial specialization - /// \c X<int>::Inner<T*> is a member specialization. - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> U Inner; - /// template<typename U> U* Inner<U*> = (U*)(0); - /// }; - /// - /// template<> template<typename T> - /// U* X<int>::Inner<T*> = (T*)(0) + 1; - /// \endcode - bool isMemberSpecialization() { - VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); - return First->InstantiatedFromMember.getInt(); - } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); - assert(First->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - return First->InstantiatedFromMember.setInt(true); - } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { - return K == VarTemplatePartialSpecialization; - } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// Declaration of a variable template. -class VarTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - -protected: - /// \brief Data that is common to all of the declarations of a given - /// variable template. - struct Common : CommonBase { - Common() : LazySpecializations() {} - - /// \brief The variable template specializations for this variable - /// template, including explicit specializations and instantiations. - llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations; - - /// \brief The variable template partial specializations for this variable - /// template. - llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> - PartialSpecializations; - - /// \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 Retrieve the set of specializations of this variable template. - llvm::FoldingSetVector<VarTemplateSpecializationDecl> & - getSpecializations() const; - - /// \brief Retrieve the set of partial specializations of this class - /// template. - llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> & - getPartialSpecializations(); - - VarTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : RedeclarableTemplateDecl(VarTemplate, C, DC, L, Name, Params, Decl) {} - - CommonBase *newCommon(ASTContext &C) const override; - - Common *getCommonPtr() const { - return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); - } - -public: - /// \brief Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations() const; - - /// \brief Get the underlying variable declarations of the template. - VarDecl *getTemplatedDecl() const { - return static_cast<VarDecl *>(TemplatedDecl); - } - - /// \brief Returns whether this template declaration defines the primary - /// variable pattern. - bool isThisDeclarationADefinition() const { - return getTemplatedDecl()->isThisDeclarationADefinition(); - } - - VarTemplateDecl *getDefinition(); - - /// \brief Create a variable template node. - static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, - VarDecl *Decl); - - /// \brief Create an empty variable template node. - static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - /// \brief Return the specialization with the provided arguments if it exists, - /// otherwise return the insertion point. - VarTemplateSpecializationDecl * - findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - - /// \brief Insert the specified specialization knowing that it is not already - /// in. InsertPos must be obtained from findSpecialization. - void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos); - - VarTemplateDecl *getCanonicalDecl() override { - return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl()); - } - const VarTemplateDecl *getCanonicalDecl() const { - return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl()); - } - - /// \brief Retrieve the previous declaration of this variable template, or - /// NULL if no such declaration exists. - VarTemplateDecl *getPreviousDecl() { - return cast_or_null<VarTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); - } - - /// \brief Retrieve the previous declaration of this variable template, or - /// NULL if no such declaration exists. - const VarTemplateDecl *getPreviousDecl() const { - return cast_or_null<VarTemplateDecl>( - static_cast<const RedeclarableTemplateDecl *>( - this)->getPreviousDecl()); - } - - VarTemplateDecl *getMostRecentDecl() { - return cast<VarTemplateDecl>( - static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl()); - } - const VarTemplateDecl *getMostRecentDecl() const { - return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl(); - } - - VarTemplateDecl *getInstantiatedFromMemberTemplate() const { - return cast_or_null<VarTemplateDecl>( - RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); - } - - /// \brief Return the partial specialization with the provided arguments if it - /// exists, otherwise return the insertion point. - VarTemplatePartialSpecializationDecl * - findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - - /// \brief Insert the specified partial specialization knowing that it is not - /// already in. InsertPos must be obtained from findPartialSpecialization. - void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D, - void *InsertPos); - - /// \brief Retrieve the partial specializations as an ordered list. - void getPartialSpecializations( - SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS); - - /// \brief Find a variable template partial specialization which was - /// instantiated - /// from the given member partial specialization. - /// - /// \param D a member variable template partial specialization. - /// - /// \returns the variable template partial specialization which was - /// instantiated - /// from the given member partial specialization, or NULL if no such partial - /// specialization exists. - VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember( - VarTemplatePartialSpecializationDecl *D); - - typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; - - spec_range specializations() const { - return spec_range(spec_begin(), spec_end()); - } - - spec_iterator spec_begin() const { - return makeSpecIterator(getSpecializations(), false); - } - - spec_iterator spec_end() const { - return makeSpecIterator(getSpecializations(), true); - } - - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == VarTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -} /* end of namespace clang */ - -#endif diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h deleted file mode 100644 index 4eaae35..0000000 --- a/include/clang/AST/DeclVisitor.h +++ /dev/null @@ -1,79 +0,0 @@ -//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- 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 DeclVisitor interface. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DECLVISITOR_H -#define LLVM_CLANG_AST_DECLVISITOR_H - -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/DeclTemplate.h" - -namespace clang { -namespace declvisitor { - -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; - -/// \brief A simple visitor class that helps create declaration visitors. -template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> -class Base { -public: - -#define PTR(CLASS) typename Ptr<CLASS>::type -#define DISPATCH(NAME, CLASS) \ - return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D)) - - RetTy Visit(PTR(Decl) D) { - switch (D->getKind()) { -#define DECL(DERIVED, BASE) \ - case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl); -#define ABSTRACT_DECL(DECL) -#include "clang/AST/DeclNodes.inc" - } - llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); - } - - // If the implementation chooses not to implement a certain visit - // method, fall back to the parent. -#define DECL(DERIVED, BASE) \ - RetTy Visit##DERIVED##Decl(PTR(DERIVED##Decl) D) { DISPATCH(BASE, BASE); } -#include "clang/AST/DeclNodes.inc" - - RetTy VisitDecl(PTR(Decl) D) { return RetTy(); } - -#undef PTR -#undef DISPATCH -}; - -} // end namespace declvisitor - -/// \brief A simple visitor class that helps create declaration visitors. -/// -/// This class does not preserve constness of Decl pointers (see also -/// ConstDeclVisitor). -template<typename ImplClass, typename RetTy=void> -class DeclVisitor - : public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {}; - -/// \brief A simple visitor class that helps create declaration visitors. -/// -/// This class preserves constness of Decl pointers (see also DeclVisitor). -template<typename ImplClass, typename RetTy=void> -class ConstDeclVisitor - : public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {}; - -} // end namespace clang - -#endif // LLVM_CLANG_AST_DECLVISITOR_H diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h deleted file mode 100644 index 9482e83e..0000000 --- a/include/clang/AST/DeclarationName.h +++ /dev/null @@ -1,598 +0,0 @@ -//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the DeclarationName and DeclarationNameTable classes. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H -#define LLVM_CLANG_AST_DECLARATIONNAME_H - -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/PartialDiagnostic.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { - template <typename T> struct DenseMapInfo; -} - -namespace clang { - class ASTContext; - class CXXLiteralOperatorIdName; - class CXXOperatorIdName; - class CXXSpecialName; - class DeclarationNameExtra; - class IdentifierInfo; - class MultiKeywordSelector; - enum OverloadedOperatorKind : int; - class QualType; - class Type; - class TypeSourceInfo; - class UsingDirectiveDecl; - - template <typename> class CanQual; - typedef CanQual<Type> CanQualType; - -/// DeclarationName - The name of a declaration. In the common case, -/// this just stores an IdentifierInfo pointer to a normal -/// name. However, it also provides encodings for Objective-C -/// selectors (optimizing zero- and one-argument selectors, which make -/// up 78% percent of all selectors in Cocoa.h) and special C++ names -/// for constructors, destructors, and conversion functions. -class DeclarationName { -public: - /// NameKind - The kind of name this object contains. - enum NameKind { - Identifier, - ObjCZeroArgSelector, - ObjCOneArgSelector, - ObjCMultiArgSelector, - CXXConstructorName, - CXXDestructorName, - CXXConversionFunctionName, - CXXOperatorName, - CXXLiteralOperatorName, - CXXUsingDirective - }; - static const unsigned NumNameKinds = CXXUsingDirective + 1; - -private: - /// StoredNameKind - The kind of name that is actually stored in the - /// upper bits of the Ptr field. This is only used internally. - /// - /// Note: The entries here are synchronized with the entries in Selector, - /// for efficient translation between the two. - enum StoredNameKind { - StoredIdentifier = 0, - StoredObjCZeroArgSelector = 0x01, - StoredObjCOneArgSelector = 0x02, - StoredDeclarationNameExtra = 0x03, - PtrMask = 0x03 - }; - - /// Ptr - The lowest two bits are used to express what kind of name - /// we're actually storing, using the values of NameKind. Depending - /// on the kind of name this is, the upper bits of Ptr may have one - /// of several different meanings: - /// - /// StoredIdentifier - The name is a normal identifier, and Ptr is - /// a normal IdentifierInfo pointer. - /// - /// StoredObjCZeroArgSelector - The name is an Objective-C - /// selector with zero arguments, and Ptr is an IdentifierInfo - /// pointer pointing to the selector name. - /// - /// StoredObjCOneArgSelector - The name is an Objective-C selector - /// with one argument, and Ptr is an IdentifierInfo pointer - /// pointing to the selector name. - /// - /// StoredDeclarationNameExtra - Ptr is actually a pointer to a - /// DeclarationNameExtra structure, whose first value will tell us - /// whether this is an Objective-C selector, C++ operator-id name, - /// or special C++ name. - uintptr_t Ptr; - - /// getStoredNameKind - Return the kind of object that is stored in - /// Ptr. - StoredNameKind getStoredNameKind() const { - return static_cast<StoredNameKind>(Ptr & PtrMask); - } - - /// getExtra - Get the "extra" information associated with this - /// multi-argument selector or C++ special name. - DeclarationNameExtra *getExtra() const { - assert(getStoredNameKind() == StoredDeclarationNameExtra && - "Declaration name does not store an Extra structure"); - return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask); - } - - /// getAsCXXSpecialName - If the stored pointer is actually a - /// CXXSpecialName, returns a pointer to it. Otherwise, returns - /// a NULL pointer. - CXXSpecialName *getAsCXXSpecialName() const { - NameKind Kind = getNameKind(); - if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName) - return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); - return nullptr; - } - - /// getAsCXXOperatorIdName - CXXOperatorIdName *getAsCXXOperatorIdName() const { - if (getNameKind() == CXXOperatorName) - return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask); - return nullptr; - } - - CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { - if (getNameKind() == CXXLiteralOperatorName) - return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask); - return nullptr; - } - - // Construct a declaration name from the name of a C++ constructor, - // destructor, or conversion function. - DeclarationName(CXXSpecialName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName"); - Ptr |= StoredDeclarationNameExtra; - } - - // Construct a declaration name from the name of a C++ overloaded - // operator. - DeclarationName(CXXOperatorIdName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId"); - Ptr |= StoredDeclarationNameExtra; - } - - DeclarationName(CXXLiteralOperatorIdName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId"); - Ptr |= StoredDeclarationNameExtra; - } - - /// Construct a declaration name from a raw pointer. - DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { } - - friend class DeclarationNameTable; - friend class NamedDecl; - - /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer - /// for this name as a void pointer if it's not an identifier. - void *getFETokenInfoAsVoidSlow() const; - -public: - /// DeclarationName - Used to create an empty selector. - DeclarationName() : Ptr(0) { } - - // Construct a declaration name from an IdentifierInfo *. - DeclarationName(const IdentifierInfo *II) - : Ptr(reinterpret_cast<uintptr_t>(II)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); - } - - // Construct a declaration name from an Objective-C selector. - DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { } - - /// getUsingDirectiveName - Return name for all using-directives. - static DeclarationName getUsingDirectiveName(); - - // operator bool() - Evaluates true when this declaration name is - // non-empty. - explicit operator bool() const { - return ((Ptr & PtrMask) != 0) || - (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask)); - } - - /// \brief Evaluates true when this declaration name is empty. - bool isEmpty() const { - return !*this; - } - - /// Predicate functions for querying what type of name this is. - bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } - bool isObjCZeroArgSelector() const { - return getStoredNameKind() == StoredObjCZeroArgSelector; - } - bool isObjCOneArgSelector() const { - return getStoredNameKind() == StoredObjCOneArgSelector; - } - - /// getNameKind - Determine what kind of name this is. - NameKind getNameKind() const; - - /// \brief Determines whether the name itself is dependent, e.g., because it - /// involves a C++ type that is itself dependent. - /// - /// Note that this does not capture all of the notions of "dependent name", - /// because an identifier can be a dependent name if it is used as the - /// callee in a call expression with dependent arguments. - bool isDependentName() const; - - /// getNameAsString - Retrieve the human-readable string for this name. - std::string getAsString() const; - - /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in - /// this declaration name, or NULL if this declaration name isn't a - /// simple identifier. - IdentifierInfo *getAsIdentifierInfo() const { - if (isIdentifier()) - return reinterpret_cast<IdentifierInfo *>(Ptr); - return nullptr; - } - - /// getAsOpaqueInteger - Get the representation of this declaration - /// name as an opaque integer. - uintptr_t getAsOpaqueInteger() const { return Ptr; } - - /// getAsOpaquePtr - Get the representation of this declaration name as - /// an opaque pointer. - void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); } - - static DeclarationName getFromOpaquePtr(void *P) { - DeclarationName N; - N.Ptr = reinterpret_cast<uintptr_t> (P); - return N; - } - - static DeclarationName getFromOpaqueInteger(uintptr_t P) { - DeclarationName N; - N.Ptr = P; - return N; - } - - /// getCXXNameType - If this name is one of the C++ names (of a - /// constructor, destructor, or conversion function), return the - /// type associated with that name. - QualType getCXXNameType() const; - - /// getCXXOverloadedOperator - If this name is the name of an - /// overloadable operator in C++ (e.g., @c operator+), retrieve the - /// kind of overloaded operator. - OverloadedOperatorKind getCXXOverloadedOperator() const; - - /// getCXXLiteralIdentifier - If this name is the name of a literal - /// operator, retrieve the identifier associated with it. - IdentifierInfo *getCXXLiteralIdentifier() const; - - /// getObjCSelector - Get the Objective-C selector stored in this - /// declaration name. - Selector getObjCSelector() const { - assert((getNameKind() == ObjCZeroArgSelector || - getNameKind() == ObjCOneArgSelector || - getNameKind() == ObjCMultiArgSelector || - Ptr == 0) && "Not a selector!"); - return Selector(Ptr); - } - - /// getFETokenInfo/setFETokenInfo - The language front-end is - /// allowed to associate arbitrary metadata with some kinds of - /// declaration names, including normal identifiers and C++ - /// constructors, destructors, and conversion functions. - template<typename T> - T *getFETokenInfo() const { - if (const IdentifierInfo *Info = getAsIdentifierInfo()) - return Info->getFETokenInfo<T>(); - return static_cast<T*>(getFETokenInfoAsVoidSlow()); - } - - void setFETokenInfo(void *T); - - /// operator== - Determine whether the specified names are identical.. - friend bool operator==(DeclarationName LHS, DeclarationName RHS) { - return LHS.Ptr == RHS.Ptr; - } - - /// operator!= - Determine whether the specified names are different. - friend bool operator!=(DeclarationName LHS, DeclarationName RHS) { - return LHS.Ptr != RHS.Ptr; - } - - static DeclarationName getEmptyMarker() { - return DeclarationName(uintptr_t(-1)); - } - - static DeclarationName getTombstoneMarker() { - return DeclarationName(uintptr_t(-2)); - } - - static int compare(DeclarationName LHS, DeclarationName RHS); - - void dump() const; -}; - -raw_ostream &operator<<(raw_ostream &OS, DeclarationName N); - -/// Ordering on two declaration names. If both names are identifiers, -/// this provides a lexicographical ordering. -inline bool operator<(DeclarationName LHS, DeclarationName RHS) { - return DeclarationName::compare(LHS, RHS) < 0; -} - -/// Ordering on two declaration names. If both names are identifiers, -/// this provides a lexicographical ordering. -inline bool operator>(DeclarationName LHS, DeclarationName RHS) { - return DeclarationName::compare(LHS, RHS) > 0; -} - -/// Ordering on two declaration names. If both names are identifiers, -/// this provides a lexicographical ordering. -inline bool operator<=(DeclarationName LHS, DeclarationName RHS) { - return DeclarationName::compare(LHS, RHS) <= 0; -} - -/// Ordering on two declaration names. If both names are identifiers, -/// this provides a lexicographical ordering. -inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { - return DeclarationName::compare(LHS, RHS) >= 0; -} - -/// DeclarationNameTable - Used to store and retrieve DeclarationName -/// instances for the various kinds of declaration names, e.g., normal -/// identifiers, C++ constructor names, etc. This class contains -/// uniqued versions of each of the C++ special names, which can be -/// retrieved using its member functions (e.g., -/// getCXXConstructorName). -class DeclarationNameTable { - const ASTContext &Ctx; - void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * - CXXOperatorIdName *CXXOperatorNames; // Operator names - void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* - - DeclarationNameTable(const DeclarationNameTable&) = delete; - void operator=(const DeclarationNameTable&) = delete; - -public: - DeclarationNameTable(const ASTContext &C); - ~DeclarationNameTable(); - - /// getIdentifier - Create a declaration name that is a simple - /// identifier. - DeclarationName getIdentifier(const IdentifierInfo *ID) { - return DeclarationName(ID); - } - - /// getCXXConstructorName - Returns the name of a C++ constructor - /// for the given Type. - DeclarationName getCXXConstructorName(CanQualType Ty); - - /// getCXXDestructorName - Returns the name of a C++ destructor - /// for the given Type. - DeclarationName getCXXDestructorName(CanQualType Ty); - - /// getCXXConversionFunctionName - Returns the name of a C++ - /// conversion function for the given Type. - DeclarationName getCXXConversionFunctionName(CanQualType Ty); - - /// getCXXSpecialName - Returns a declaration name for special kind - /// of C++ name, e.g., for a constructor, destructor, or conversion - /// function. - DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, - CanQualType Ty); - - /// getCXXOperatorName - Get the name of the overloadable C++ - /// operator corresponding to Op. - DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); - - /// getCXXLiteralOperatorName - Get the name of the literal operator function - /// with II as the identifier. - DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); -}; - -/// DeclarationNameLoc - Additional source/type location info -/// for a declaration name. Needs a DeclarationName in order -/// to be interpreted correctly. -struct DeclarationNameLoc { - // The source location for identifier stored elsewhere. - // struct {} Identifier; - - // Type info for constructors, destructors and conversion functions. - // Locations (if any) for the tilde (destructor) or operator keyword - // (conversion) are stored elsewhere. - struct NT { - TypeSourceInfo *TInfo; - }; - - // The location (if any) of the operator keyword is stored elsewhere. - struct CXXOpName { - unsigned BeginOpNameLoc; - unsigned EndOpNameLoc; - }; - - // The location (if any) of the operator keyword is stored elsewhere. - struct CXXLitOpName { - unsigned OpNameLoc; - }; - - // struct {} CXXUsingDirective; - // struct {} ObjCZeroArgSelector; - // struct {} ObjCOneArgSelector; - // struct {} ObjCMultiArgSelector; - union { - struct NT NamedType; - struct CXXOpName CXXOperatorName; - struct CXXLitOpName CXXLiteralOperatorName; - }; - - DeclarationNameLoc(DeclarationName Name); - // FIXME: this should go away once all DNLocs are properly initialized. - DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); } -}; // struct DeclarationNameLoc - - -/// DeclarationNameInfo - A collector data type for bundling together -/// a DeclarationName and the correspnding source/type location info. -struct DeclarationNameInfo { -private: - /// Name - The declaration name, also encoding name kind. - DeclarationName Name; - /// Loc - The main source location for the declaration name. - SourceLocation NameLoc; - /// Info - Further source/type location info for special kinds of names. - DeclarationNameLoc LocInfo; - -public: - // FIXME: remove it. - DeclarationNameInfo() {} - - DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc) - : Name(Name), NameLoc(NameLoc), LocInfo(Name) {} - - DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc, - DeclarationNameLoc LocInfo) - : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {} - - /// getName - Returns the embedded declaration name. - DeclarationName getName() const { return Name; } - /// setName - Sets the embedded declaration name. - void setName(DeclarationName N) { Name = N; } - - /// getLoc - Returns the main location of the declaration name. - SourceLocation getLoc() const { return NameLoc; } - /// setLoc - Sets the main location of the declaration name. - void setLoc(SourceLocation L) { NameLoc = L; } - - const DeclarationNameLoc &getInfo() const { return LocInfo; } - DeclarationNameLoc &getInfo() { return LocInfo; } - void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; } - - /// getNamedTypeInfo - Returns the source type info associated to - /// the name. Assumes it is a constructor, destructor or conversion. - TypeSourceInfo *getNamedTypeInfo() const { - assert(Name.getNameKind() == DeclarationName::CXXConstructorName || - Name.getNameKind() == DeclarationName::CXXDestructorName || - Name.getNameKind() == DeclarationName::CXXConversionFunctionName); - return LocInfo.NamedType.TInfo; - } - /// setNamedTypeInfo - Sets the source type info associated to - /// the name. Assumes it is a constructor, destructor or conversion. - void setNamedTypeInfo(TypeSourceInfo *TInfo) { - assert(Name.getNameKind() == DeclarationName::CXXConstructorName || - Name.getNameKind() == DeclarationName::CXXDestructorName || - Name.getNameKind() == DeclarationName::CXXConversionFunctionName); - LocInfo.NamedType.TInfo = TInfo; - } - - /// getCXXOperatorNameRange - Gets the range of the operator name - /// (without the operator keyword). Assumes it is a (non-literal) operator. - SourceRange getCXXOperatorNameRange() const { - assert(Name.getNameKind() == DeclarationName::CXXOperatorName); - return SourceRange( - SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc), - SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc) - ); - } - /// setCXXOperatorNameRange - Sets the range of the operator name - /// (without the operator keyword). Assumes it is a C++ operator. - void setCXXOperatorNameRange(SourceRange R) { - assert(Name.getNameKind() == DeclarationName::CXXOperatorName); - LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding(); - LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding(); - } - - /// getCXXLiteralOperatorNameLoc - Returns the location of the literal - /// operator name (not the operator keyword). - /// Assumes it is a literal operator. - SourceLocation getCXXLiteralOperatorNameLoc() const { - assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); - return SourceLocation:: - getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc); - } - /// setCXXLiteralOperatorNameLoc - Sets the location of the literal - /// operator name (not the operator keyword). - /// Assumes it is a literal operator. - void setCXXLiteralOperatorNameLoc(SourceLocation Loc) { - assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); - LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); - } - - /// \brief Determine whether this name involves a template parameter. - bool isInstantiationDependent() const; - - /// \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; - - /// printName - Print the human-readable name to a stream. - void printName(raw_ostream &OS) const; - - /// getBeginLoc - Retrieve the location of the first token. - SourceLocation getBeginLoc() const { return NameLoc; } - /// getEndLoc - Retrieve the location of the last token. - SourceLocation getEndLoc() const; - /// getSourceRange - The range of the declaration name. - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocStart(), getLocEnd()); - } - SourceLocation getLocStart() const LLVM_READONLY { - return getBeginLoc(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - SourceLocation EndLoc = getEndLoc(); - return EndLoc.isValid() ? EndLoc : getLocStart(); - } -}; - -/// Insertion operator for diagnostics. This allows sending DeclarationName's -/// into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - DeclarationName N) { - DB.AddTaggedVal(N.getAsOpaqueInteger(), - DiagnosticsEngine::ak_declarationname); - return DB; -} - -/// Insertion operator for partial diagnostics. This allows binding -/// DeclarationName's into a partial diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - DeclarationName N) { - PD.AddTaggedVal(N.getAsOpaqueInteger(), - DiagnosticsEngine::ak_declarationname); - return PD; -} - -inline raw_ostream &operator<<(raw_ostream &OS, - DeclarationNameInfo DNInfo) { - DNInfo.printName(OS); - return OS; -} - -} // end namespace clang - -namespace llvm { -/// Define DenseMapInfo so that DeclarationNames can be used as keys -/// in DenseMap and DenseSets. -template<> -struct DenseMapInfo<clang::DeclarationName> { - static inline clang::DeclarationName getEmptyKey() { - return clang::DeclarationName::getEmptyMarker(); - } - - static inline clang::DeclarationName getTombstoneKey() { - return clang::DeclarationName::getTombstoneMarker(); - } - - static unsigned getHashValue(clang::DeclarationName Name) { - return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr()); - } - - static inline bool - isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { - return LHS == RHS; - } -}; - -template <> -struct isPodLike<clang::DeclarationName> { static const bool value = true; }; - -} // end namespace llvm - -#endif diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h deleted file mode 100644 index 8e038c8..0000000 --- a/include/clang/AST/DependentDiagnostic.h +++ /dev/null @@ -1,189 +0,0 @@ -//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- 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 interfaces for diagnostics which may or may -// fire based on how a template is instantiated. -// -// At the moment, the only consumer of this interface is access -// control. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H -#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H - -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/Type.h" -#include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/SourceLocation.h" - -namespace clang { - -class ASTContext; -class CXXRecordDecl; -class NamedDecl; - -/// A dependently-generated diagnostic. -class DependentDiagnostic { -public: - enum AccessNonce { Access = 0 }; - - static DependentDiagnostic *Create(ASTContext &Context, - DeclContext *Parent, - AccessNonce _, - SourceLocation Loc, - bool IsMemberAccess, - AccessSpecifier AS, - NamedDecl *TargetDecl, - CXXRecordDecl *NamingClass, - QualType BaseObjectType, - const PartialDiagnostic &PDiag) { - DependentDiagnostic *DD = Create(Context, Parent, PDiag); - DD->AccessData.Loc = Loc.getRawEncoding(); - DD->AccessData.IsMember = IsMemberAccess; - DD->AccessData.Access = AS; - DD->AccessData.TargetDecl = TargetDecl; - DD->AccessData.NamingClass = NamingClass; - DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr(); - return DD; - } - - unsigned getKind() const { - return Access; - } - - bool isAccessToMember() const { - assert(getKind() == Access); - return AccessData.IsMember; - } - - AccessSpecifier getAccess() const { - assert(getKind() == Access); - return AccessSpecifier(AccessData.Access); - } - - SourceLocation getAccessLoc() const { - assert(getKind() == Access); - return SourceLocation::getFromRawEncoding(AccessData.Loc); - } - - NamedDecl *getAccessTarget() const { - assert(getKind() == Access); - return AccessData.TargetDecl; - } - - NamedDecl *getAccessNamingClass() const { - assert(getKind() == Access); - return AccessData.NamingClass; - } - - QualType getAccessBaseObjectType() const { - assert(getKind() == Access); - return QualType::getFromOpaquePtr(AccessData.BaseObjectType); - } - - const PartialDiagnostic &getDiagnostic() const { - return Diag; - } - -private: - DependentDiagnostic(const PartialDiagnostic &PDiag, - PartialDiagnostic::Storage *Storage) - : Diag(PDiag, Storage) {} - - static DependentDiagnostic *Create(ASTContext &Context, - DeclContext *Parent, - const PartialDiagnostic &PDiag); - - friend class DependentStoredDeclsMap; - friend class DeclContext::ddiag_iterator; - DependentDiagnostic *NextDiagnostic; - - PartialDiagnostic Diag; - - struct { - unsigned Loc; - unsigned Access : 2; - unsigned IsMember : 1; - NamedDecl *TargetDecl; - CXXRecordDecl *NamingClass; - void *BaseObjectType; - } AccessData; -}; - -/// - -/// An iterator over the dependent diagnostics in a dependent context. -class DeclContext::ddiag_iterator { -public: - ddiag_iterator() : Ptr(nullptr) {} - explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} - - typedef DependentDiagnostic *value_type; - typedef DependentDiagnostic *reference; - typedef DependentDiagnostic *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; - - reference operator*() const { return Ptr; } - - ddiag_iterator &operator++() { - assert(Ptr && "attempt to increment past end of diag list"); - Ptr = Ptr->NextDiagnostic; - return *this; - } - - ddiag_iterator operator++(int) { - ddiag_iterator tmp = *this; - ++*this; - return tmp; - } - - bool operator==(ddiag_iterator Other) const { - return Ptr == Other.Ptr; - } - - bool operator!=(ddiag_iterator Other) const { - return Ptr != Other.Ptr; - } - - ddiag_iterator &operator+=(difference_type N) { - assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); - while (N--) - ++*this; - return *this; - } - - ddiag_iterator operator+(difference_type N) const { - ddiag_iterator tmp = *this; - tmp += N; - return tmp; - } - -private: - DependentDiagnostic *Ptr; -}; - -inline DeclContext::ddiag_range DeclContext::ddiags() const { - assert(isDependentContext() - && "cannot iterate dependent diagnostics of non-dependent context"); - const DependentStoredDeclsMap *Map - = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); - - if (!Map) - // Return an empty range using the always-end default constructor. - return ddiag_range(ddiag_iterator(), ddiag_iterator()); - - return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); -} - -} - -#endif diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h deleted file mode 100644 index aad7726..0000000 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ /dev/null @@ -1,129 +0,0 @@ -//===--- 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/DeclCXX.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtVisitor.h" - -namespace clang { - -class ASTContext; - -/// \brief Given a potentially-evaluated expression, this visitor visits all -/// of its potentially-evaluated subexpressions, recursively. -template<template <typename> class Ptr, typename ImplClass> -class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> { -protected: - const ASTContext &Context; - -public: -#define PTR(CLASS) typename Ptr<CLASS>::type - - explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { } - - // Expressions that have no potentially-evaluated subexpressions (but may have - // other sub-expressions). - void VisitDeclRefExpr(PTR(DeclRefExpr) E) { } - void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { } - void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { } - void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { } - void VisitBlockExpr(PTR(BlockExpr) E) { } - void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { } - void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { } - - void VisitMemberExpr(PTR(MemberExpr) E) { - // Only the base matters. - return this->Visit(E->getBase()); - } - - void VisitChooseExpr(PTR(ChooseExpr) E) { - // Don't visit either child expression if the condition is dependent. - if (E->getCond()->isValueDependent()) - return; - // Only the selected subexpression matters; the other one is not evaluated. - return this->Visit(E->getChosenSubExpr()); - } - - void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) { - // The controlling expression of a generic selection is not evaluated. - - // Don't visit either child expression if the condition is type-dependent. - if (E->isResultDependent()) - return; - // Only the selected subexpression matters; the other subexpressions and the - // controlling expression are not evaluated. - return this->Visit(E->getResultExpr()); - } - - void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) { - // Only the actual initializer matters; the designators are all constant - // expressions. - return this->Visit(E->getInit()); - } - - void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) { - if (E->isPotentiallyEvaluated()) - return this->Visit(E->getExprOperand()); - } - - void VisitCallExpr(PTR(CallExpr) CE) { - if (!CE->isUnevaluatedBuiltinCall(Context)) - return static_cast<ImplClass*>(this)->VisitExpr(CE); - } - - void VisitLambdaExpr(PTR(LambdaExpr) LE) { - // Only visit the capture initializers, and not the body. - for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(), - E = LE->capture_init_end(); - I != E; ++I) - if (*I) - this->Visit(*I); - } - - /// \brief The basis case walks all of the children of the statement or - /// expression, assuming they are all potentially evaluated. - void VisitStmt(PTR(Stmt) S) { - for (auto *SubStmt : S->children()) - if (SubStmt) - this->Visit(SubStmt); - } - -#undef PTR -}; - -/// EvaluatedExprVisitor - This class visits 'Expr *'s -template<typename ImplClass> -class EvaluatedExprVisitor - : public EvaluatedExprVisitorBase<make_ptr, ImplClass> { -public: - explicit EvaluatedExprVisitor(const ASTContext &Context) : - EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { } -}; - -/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s. -template<typename ImplClass> -class ConstEvaluatedExprVisitor - : public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> { -public: - explicit ConstEvaluatedExprVisitor(const ASTContext &Context) : - EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { } -}; - -} - -#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h deleted file mode 100644 index 095dd6a..0000000 --- a/include/clang/AST/Expr.h +++ /dev/null @@ -1,4941 +0,0 @@ -//===--- Expr.h - Classes for representing expressions ----------*- 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 Expr interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_EXPR_H -#define LLVM_CLANG_AST_EXPR_H - -#include "clang/AST/APValue.h" -#include "clang/AST/ASTVector.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclAccessPair.h" -#include "clang/AST/OperationKinds.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" -#include "clang/Basic/CharInfo.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/TypeTraits.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - class APValue; - class ASTContext; - class BlockDecl; - class CXXBaseSpecifier; - class CXXMemberCallExpr; - class CXXOperatorCallExpr; - class CastExpr; - class Decl; - class IdentifierInfo; - class MaterializeTemporaryExpr; - class NamedDecl; - class ObjCPropertyRefExpr; - class OpaqueValueExpr; - class ParmVarDecl; - class StringLiteral; - class TargetInfo; - class ValueDecl; - -/// \brief A simple array of base specifiers. -typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; - -/// \brief An adjustment to be made to the temporary created when emitting a -/// reference binding, which accesses a particular subobject of that temporary. -struct SubobjectAdjustment { - enum { - DerivedToBaseAdjustment, - FieldAdjustment, - MemberPointerAdjustment - } Kind; - - struct DTB { - const CastExpr *BasePath; - const CXXRecordDecl *DerivedClass; - }; - - struct P { - const MemberPointerType *MPT; - Expr *RHS; - }; - - union { - struct DTB DerivedToBase; - FieldDecl *Field; - struct P Ptr; - }; - - SubobjectAdjustment(const CastExpr *BasePath, - const CXXRecordDecl *DerivedClass) - : Kind(DerivedToBaseAdjustment) { - DerivedToBase.BasePath = BasePath; - DerivedToBase.DerivedClass = DerivedClass; - } - - SubobjectAdjustment(FieldDecl *Field) - : Kind(FieldAdjustment) { - this->Field = Field; - } - - SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS) - : Kind(MemberPointerAdjustment) { - this->Ptr.MPT = MPT; - this->Ptr.RHS = RHS; - } -}; - -/// Expr - This represents one expression. Note that Expr's are subclasses of -/// Stmt. This allows an expression to be transparently used any place a Stmt -/// is required. -/// -class Expr : public Stmt { - QualType TR; - -protected: - Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) - : Stmt(SC) - { - ExprBits.TypeDependent = TD; - ExprBits.ValueDependent = VD; - ExprBits.InstantiationDependent = ID; - ExprBits.ValueKind = VK; - ExprBits.ObjectKind = OK; - ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; - setType(T); - } - - /// \brief Construct an empty expression. - explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } - -public: - QualType getType() const { return TR; } - void setType(QualType t) { - // In C++, the type of an expression is always adjusted so that it - // will not have reference type (C++ [expr]p6). Use - // QualType::getNonReferenceType() to retrieve the non-reference - // type. Additionally, inspect Expr::isLvalue to determine whether - // an expression that is adjusted in this manner should be - // considered an lvalue. - assert((t.isNull() || !t->isReferenceType()) && - "Expressions can't have reference type"); - - TR = t; - } - - /// isValueDependent - Determines whether this expression is - /// value-dependent (C++ [temp.dep.constexpr]). For example, the - /// array bound of "Chars" in the following example is - /// value-dependent. - /// @code - /// template<int Size, char (&Chars)[Size]> struct meta_string; - /// @endcode - bool isValueDependent() const { return ExprBits.ValueDependent; } - - /// \brief Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { - ExprBits.ValueDependent = VD; - } - - /// isTypeDependent - Determines whether this expression is - /// type-dependent (C++ [temp.dep.expr]), which means that its type - /// could change from one template instantiation to the next. For - /// example, the expressions "x" and "x + y" are type-dependent in - /// the following code, but "y" is not type-dependent: - /// @code - /// template<typename T> - /// void add(T x, int y) { - /// x + y; - /// } - /// @endcode - bool isTypeDependent() const { return ExprBits.TypeDependent; } - - /// \brief Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { - ExprBits.TypeDependent = TD; - } - - /// \brief Whether this expression is instantiation-dependent, meaning that - /// it depends in some way on a template parameter, even if neither its type - /// nor (constant) value can change due to the template instantiation. - /// - /// In the following example, the expression \c sizeof(sizeof(T() + T())) is - /// instantiation-dependent (since it involves a template parameter \c T), but - /// is neither type- nor value-dependent, since the type of the inner - /// \c sizeof is known (\c std::size_t) and therefore the size of the outer - /// \c sizeof is known. - /// - /// \code - /// template<typename T> - /// void f(T x, T y) { - /// sizeof(sizeof(T() + T()); - /// } - /// \endcode - /// - bool isInstantiationDependent() const { - return ExprBits.InstantiationDependent; - } - - /// \brief Set whether this expression is instantiation-dependent or not. - void setInstantiationDependent(bool ID) { - ExprBits.InstantiationDependent = ID; - } - - /// \brief Whether this expression contains an unexpanded parameter - /// pack (for C++11 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; - } - - /// \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. - SourceLocation getExprLoc() const LLVM_READONLY; - - /// isUnusedResultAWarning - Return true if this immediate expression should - /// be warned about if the result is unused. If so, fill in expr, location, - /// and ranges with expr to warn on and source locations/ranges appropriate - /// for a warning. - bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc, - SourceRange &R1, SourceRange &R2, - ASTContext &Ctx) const; - - /// 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. - /// - /// C++11 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, - LV_DuplicateVectorComponents, - LV_InvalidExpression, - LV_InvalidMessageExpression, - LV_MemberFunction, - LV_SubObjCPropertySetting, - LV_ClassTemporary, - LV_ArrayTemporary - }; - /// Reasons why an expression might not be an l-value. - LValueClassification ClassifyLValue(ASTContext &Ctx) const; - - enum isModifiableLvalueResult { - MLV_Valid, - MLV_NotObjectType, - MLV_IncompleteVoidType, - MLV_DuplicateVectorComponents, - MLV_InvalidExpression, - MLV_LValueCast, // Specialized form of MLV_InvalidExpression. - MLV_IncompleteType, - MLV_ConstQualified, - MLV_ConstAddrSpace, - MLV_ArrayType, - MLV_NoSetterProperty, - MLV_MemberFunction, - MLV_SubObjCPropertySetting, - MLV_InvalidMessageExpression, - MLV_ClassTemporary, - MLV_ArrayTemporary - }; - /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, - /// does not have an incomplete type, does not have a const-qualified type, - /// and if it is a structure or union, does not have any member (including, - /// recursively, any member or element of all contained aggregates or unions) - /// with a const-qualified type. - /// - /// \param Loc [in,out] - A source location which *may* be filled - /// in with the location of the expression making this a - /// non-modifiable lvalue, if specified. - isModifiableLvalueResult - isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const; - - /// \brief The return type of classify(). Represents the C++11 expression - /// taxonomy. - class Classification { - public: - /// \brief The various classification results. Most of these mean prvalue. - enum Kinds { - CL_LValue, - CL_XValue, - CL_Function, // Functions cannot be lvalues in C. - CL_Void, // Void cannot be an lvalue in C. - CL_AddressableVoid, // Void expression whose address can be taken in C. - CL_DuplicateVectorComponents, // A vector shuffle with dupes. - CL_MemberFunction, // An expression referring to a member function - CL_SubObjCPropertySetting, - CL_ClassTemporary, // A temporary of class type, or subobject thereof. - CL_ArrayTemporary, // A temporary of array type. - CL_ObjCMessageRValue, // ObjC message is an rvalue - CL_PRValue // A prvalue for any other reason, of any other type - }; - /// \brief The results of modification testing. - enum ModifiableType { - CM_Untested, // testModifiable was false. - CM_Modifiable, - CM_RValue, // Not modifiable because it's an rvalue - CM_Function, // Not modifiable because it's a function; C++ only - CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext - CM_NoSetterProperty,// Implicit assignment to ObjC property without setter - CM_ConstQualified, - CM_ConstAddrSpace, - CM_ArrayType, - CM_IncompleteType - }; - - private: - friend class Expr; - - unsigned short Kind; - unsigned short Modifiable; - - explicit Classification(Kinds k, ModifiableType m) - : Kind(k), Modifiable(m) - {} - - public: - Classification() {} - - Kinds getKind() const { return static_cast<Kinds>(Kind); } - ModifiableType getModifiable() const { - assert(Modifiable != CM_Untested && "Did not test for modifiability."); - return static_cast<ModifiableType>(Modifiable); - } - bool isLValue() const { return Kind == CL_LValue; } - bool isXValue() const { return Kind == CL_XValue; } - bool isGLValue() const { return Kind <= CL_XValue; } - 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++11 - /// expression taxonomy. - /// - /// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the - /// old lvalue vs rvalue. This function determines the type of expression this - /// is. There are three expression types: - /// - lvalues are classical lvalues as in C++03. - /// - prvalues are equivalent to rvalues in C++03. - /// - xvalues are expressions yielding unnamed rvalue references, e.g. a - /// function returning an rvalue reference. - /// lvalues and xvalues are collectively referred to as glvalues, while - /// prvalues and xvalues together form rvalues. - Classification Classify(ASTContext &Ctx) const { - return ClassifyImpl(Ctx, nullptr); - } - - /// \brief ClassifyModifiable - Classify this expression according to the - /// C++11 expression taxonomy, and see if it is valid on the left side - /// of an assignment. - /// - /// This function extends classify in that it also tests whether the - /// expression is modifiable (C99 6.3.2.1p1). - /// \param Loc A source location that might be filled with a relevant location - /// if the expression is not modifiable. - Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{ - 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; - -public: - - /// \brief Returns true if this expression is a gl-value that - /// potentially refers to a bit-field. - /// - /// In C++, whether a gl-value refers to a bitfield is essentially - /// an aspect of the value-kind type system. - bool refersToBitField() const { return getObjectKind() == OK_BitField; } - - /// \brief If this expression refers to a bit-field, retrieve the - /// declaration of that bit-field. - /// - /// Note that this returns a non-null pointer in subtly different - /// places than refersToBitField returns true. In particular, this can - /// return a non-null pointer even for r-values loaded from - /// bit-fields, but it will return null for a conditional bit-field. - FieldDecl *getSourceBitField(); - - const FieldDecl *getSourceBitField() const { - return const_cast<Expr*>(this)->getSourceBitField(); - } - - /// \brief If this expression is an l-value for an Objective C - /// property, find the underlying property reference expression. - const ObjCPropertyRefExpr *getObjCProperty() const; - - /// \brief Check if this expression is the ObjC 'self' implicit parameter. - bool isObjCSelfExpr() const; - - /// \brief Returns whether this expression refers to a vector element. - bool refersToVectorElement() const; - - /// \brief Returns whether this expression refers to a global register - /// variable. - bool refersToGlobalRegisterVar() const; - - /// \brief Returns whether this expression has a placeholder type. - bool hasPlaceholderType() const { - return getType()->isPlaceholderType(); - } - - /// \brief Returns whether this expression has a specific placeholder type. - bool hasPlaceholderType(BuiltinType::Kind K) const { - assert(BuiltinType::isPlaceholderTypeKind(K)); - if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType())) - return BT->getKind() == K; - return false; - } - - /// isKnownToHaveBooleanValue - Return true if this is an integer expression - /// that is known to return 0 or 1. This happens for _Bool/bool expressions - /// but also int expressions which are produced by things like comparisons in - /// C. - bool isKnownToHaveBooleanValue() const; - - /// isIntegerConstantExpr - Return true if this expression is a valid integer - /// constant expression, and, if so, return its value in Result. If not a - /// valid i-c-e, return false and fill in Loc (if specified) with the location - /// of the invalid expression. - /// - /// Note: This does not perform the implicit conversions required by C++11 - /// [expr.const]p5. - bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, - SourceLocation *Loc = nullptr, - bool isEvaluated = true) const; - bool isIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc = nullptr) const; - - /// isCXX98IntegralConstantExpr - Return true if this expression is an - /// integral constant expression in C++98. Can only be used in C++. - bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const; - - /// isCXX11ConstantExpr - Return true if this expression is a constant - /// expression in C++11. Can only be used in C++. - /// - /// Note: This does not perform the implicit conversions required by C++11 - /// [expr.const]p5. - bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr, - SourceLocation *Loc = nullptr) const; - - /// isPotentialConstantExpr - Return true if this function's definition - /// might be usable in a constant expression in C++11, if it were marked - /// constexpr. Return false if the function can never produce a constant - /// expression, along with diagnostics describing why not. - static bool isPotentialConstantExpr(const FunctionDecl *FD, - SmallVectorImpl< - PartialDiagnosticAt> &Diags); - - /// isPotentialConstantExprUnevaluted - Return true if this expression might - /// be usable in a constant expression in C++11 in an unevaluated context, if - /// it were in function FD marked constexpr. Return false if the function can - /// never produce a constant expression, along with diagnostics describing - /// why not. - static bool isPotentialConstantExprUnevaluated(Expr *E, - const FunctionDecl *FD, - SmallVectorImpl< - PartialDiagnosticAt> &Diags); - - /// isConstantInitializer - Returns true if this expression can be emitted to - /// IR as a constant, and thus can be used as a constant initializer in C. - /// If this expression is not constant and Culprit is non-null, - /// it is used to store the address of first non constant expr. - bool isConstantInitializer(ASTContext &Ctx, bool ForRef, - const Expr **Culprit = nullptr) const; - - /// EvalStatus is a struct with detailed info about an evaluation in progress. - struct EvalStatus { - /// \brief Whether the evaluated expression has side effects. - /// For example, (f() && 0) can be folded, but it still has side effects. - bool HasSideEffects; - - /// \brief Whether the evaluation hit undefined behavior. - /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. - /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. - bool HasUndefinedBehavior; - - /// Diag - If this is non-null, it will be filled in with a stack of notes - /// indicating why evaluation failed (or why it failed to produce a constant - /// expression). - /// If the expression is unfoldable, the notes will indicate why it's not - /// foldable. If the expression is foldable, but not a constant expression, - /// the notes will describes why it isn't a constant expression. If the - /// expression *is* a constant expression, no notes will be produced. - SmallVectorImpl<PartialDiagnosticAt> *Diag; - - EvalStatus() - : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {} - - // hasSideEffects - Return true if the evaluated expression has - // side effects. - bool hasSideEffects() const { - return HasSideEffects; - } - }; - - /// EvalResult is a struct with detailed info about an evaluated expression. - struct EvalResult : EvalStatus { - /// Val - This is the value the expression can be folded to. - APValue Val; - - // isGlobalLValue - Return true if the evaluated lvalue expression - // is global. - bool isGlobalLValue() const; - }; - - /// EvaluateAsRValue - Return true if this is a constant which we can fold to - /// an rvalue using any crazy technique (that has nothing to do with language - /// standards) that we want to, even if the expression has side-effects. If - /// this function returns true, it returns the folded constant in Result. If - /// the expression is a glvalue, an lvalue-to-rvalue conversion will be - /// applied. - bool EvaluateAsRValue(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, even if the expression has - /// side-effects. - bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; - - enum SideEffectsKind { - SE_NoSideEffects, ///< Strictly evaluate the expression. - SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not - ///< arbitrary unmodeled side effects. - SE_AllowSideEffects ///< Allow any unmodeled side effect. - }; - - /// EvaluateAsInt - Return true if this is a constant which we can fold and - /// convert to an integer, using any crazy technique that we want to. - bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; - - /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be - /// constant folded without side-effects, but discard the result. - bool isEvaluatable(const ASTContext &Ctx, - SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; - - /// HasSideEffects - This routine returns true for all those expressions - /// which have any effect other than producing a value. Example is a function - /// call, volatile variable read, or throwing an exception. If - /// IncludePossibleEffects is false, this call treats certain expressions with - /// potential side effects (such as function call-like expressions, - /// instantiation-dependent expressions, or invocations from a macro) as not - /// having side effects. - bool HasSideEffects(const ASTContext &Ctx, - bool IncludePossibleEffects = true) const; - - /// \brief Determine whether this expression involves a call to any function - /// that is not trivial. - bool hasNonTrivialCall(const ASTContext &Ctx) const; - - /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded - /// integer. This must be called on an expression that constant folds to an - /// integer. - llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, - SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; - - void EvaluateForOverflow(const ASTContext &Ctx) const; - - /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an - /// lvalue with link time known address, with no side-effects. - bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const; - - /// EvaluateAsInitializer - Evaluate an expression as if it were the - /// initializer of the given declaration. Returns true if the initializer - /// can be folded to a constant, and produces any relevant notes. In C++11, - /// notes will be produced if the expression is not a constant expression. - bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, - const VarDecl *VD, - SmallVectorImpl<PartialDiagnosticAt> &Notes) const; - - /// EvaluateWithSubstitution - Evaluate an expression as if from the context - /// of a call to the given function with the given arguments, inside an - /// unevaluated context. Returns true if the expression could be folded to a - /// constant. - bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, - const FunctionDecl *Callee, - ArrayRef<const Expr*> Args) const; - - /// \brief If the current Expr is a pointer, this will try to statically - /// determine the number of bytes available where the pointer is pointing. - /// Returns true if all of the above holds and we were able to figure out the - /// size, false otherwise. - /// - /// \param Type - How to evaluate the size of the Expr, as defined by the - /// "type" parameter of __builtin_object_size - bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, - unsigned Type) 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 - /// expression that is not a simple, possibly parenthesized, zero literal. - /// C++ Core Issue 903 will classify these expressions as "not pointers" - /// once it is adopted. - /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 - NPCK_ZeroExpression, - - /// \brief Expression is a Null pointer constant built from a literal zero. - NPCK_ZeroLiteral, - - /// \brief Expression is a C++11 nullptr. - NPCK_CXX11_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. - enum NullPointerConstantValueDependence { - /// \brief Specifies that the expression should never be value-dependent. - NPC_NeverValueDependent = 0, - - /// \brief Specifies that a value-dependent expression of integral or - /// dependent type should be considered a null pointer constant. - NPC_ValueDependentIsNull, - - /// \brief Specifies that a value-dependent expression should be considered - /// to never be a null pointer constant. - NPC_ValueDependentIsNotNull - }; - - /// isNullPointerConstant - C99 6.3.2.3p3 - 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 Given an expression of bound-member type, find the type - /// of the member. Returns null if this is an *overloaded* bound - /// member expression. - static QualType findBoundMemberType(const Expr *expr); - - /// IgnoreImpCasts - Skip past any implicit casts which might - /// surround this expression. Only skips ImplicitCastExprs. - Expr *IgnoreImpCasts() LLVM_READONLY; - - /// IgnoreImplicit - Skip past any implicit AST nodes which might - /// surround this expression. - Expr *IgnoreImplicit() LLVM_READONLY { - return cast<Expr>(Stmt::IgnoreImplicit()); - } - - const Expr *IgnoreImplicit() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreImplicit(); - } - - /// 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. - /// Otherwise, the method returns the current Expr. - Expr *IgnoreParens() LLVM_READONLY; - - /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr - /// or CastExprs, returning their operand. - Expr *IgnoreParenCasts() LLVM_READONLY; - - /// Ignore casts. Strip off any CastExprs, returning their operand. - Expr *IgnoreCasts() LLVM_READONLY; - - /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off - /// any ParenExpr or ImplicitCastExprs, returning their operand. - Expr *IgnoreParenImpCasts() LLVM_READONLY; - - /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a - /// call to a conversion operator, return the argument. - Expr *IgnoreConversionOperator() LLVM_READONLY; - - const Expr *IgnoreConversionOperator() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreConversionOperator(); - } - - const Expr *IgnoreParenImpCasts() const LLVM_READONLY { - 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() LLVM_READONLY; - - const Expr *IgnoreParenLValueCasts() const LLVM_READONLY { - 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. - Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; - - /// Ignore parentheses and derived-to-base casts. - Expr *ignoreParenBaseCasts() LLVM_READONLY; - - const Expr *ignoreParenBaseCasts() const LLVM_READONLY { - return const_cast<Expr*>(this)->ignoreParenBaseCasts(); - } - - /// \brief Determine whether this expression is a default function argument. - /// - /// Default arguments are implicitly generated in the abstract syntax tree - /// by semantic analysis for function calls, object constructions, etc. in - /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes; - /// this routine also looks through any implicit casts to determine whether - /// the expression is a default argument. - bool isDefaultArgument() 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; - - /// \brief Whether this expression is an implicit reference to 'this' in C++. - bool isImplicitCXXThis() const; - - const Expr *IgnoreImpCasts() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreImpCasts(); - } - const Expr *IgnoreParens() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreParens(); - } - const Expr *IgnoreParenCasts() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreParenCasts(); - } - /// Strip off casts, but keep parentheses. - const Expr *IgnoreCasts() const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreCasts(); - } - - const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { - return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); - } - - static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs); - - /// \brief For an expression of class type or pointer to class type, - /// return the most derived class decl the expression is known to refer to. - /// - /// If this expression is a cast, this method looks through it to find the - /// most derived decl that can be inferred from the expression. - /// This is valid because derived-to-base conversions have undefined - /// behavior if the object isn't dynamically of the derived type. - const CXXRecordDecl *getBestDynamicClassType() const; - - /// Walk outwards from an expression we want to bind a reference to and - /// find the expression whose lifetime needs to be extended. Record - /// the LHSs of comma expressions and adjustments needed along the path. - const Expr *skipRValueSubobjectAdjustments( - SmallVectorImpl<const Expr *> &CommaLHS, - SmallVectorImpl<SubobjectAdjustment> &Adjustments) const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() >= firstExprConstant && - T->getStmtClass() <= lastExprConstant; - } -}; - -//===----------------------------------------------------------------------===// -// 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 *SourceExpr = nullptr) - : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), - T->isDependentType() || - (SourceExpr && SourceExpr->isValueDependent()), - T->isInstantiationDependentType(), - false), - SourceExpr(SourceExpr), 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; } - - SourceLocation getLocStart() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getLocStart() : Loc; - } - SourceLocation getLocEnd() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getLocEnd() : Loc; - } - SourceLocation getExprLoc() const LLVM_READONLY { - if (SourceExpr) return SourceExpr->getExprLoc(); - return Loc; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - /// 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; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OpaqueValueExprClass; - } -}; - -/// \brief A reference to a declared variable, function, enum, etc. -/// [C99 6.5.1p2] -/// -/// This encodes all the information about how a declaration is referenced -/// within an expression. -/// -/// There are several optional constructs attached to DeclRefExprs only when -/// they apply in order to conserve memory. These are laid out past the end of -/// the object, and flags in the DeclRefExprBitfield track whether they exist: -/// -/// DeclRefExprBits.HasQualifier: -/// Specifies when this declaration reference expression has a C++ -/// nested-name-specifier. -/// DeclRefExprBits.HasFoundDecl: -/// Specifies when this declaration reference expression has a record of -/// a NamedDecl (different from the referenced ValueDecl) which was found -/// during name lookup and/or overload resolution. -/// DeclRefExprBits.HasTemplateKWAndArgsInfo: -/// Specifies when this declaration reference expression has an explicit -/// C++ template keyword and/or template argument list. -/// DeclRefExprBits.RefersToEnclosingVariableOrCapture -/// Specifies when this declaration reference expression (validly) -/// refers to an enclosed local or a captured variable. -class DeclRefExpr final - : public Expr, - private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, - NamedDecl *, ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { - /// \brief The declaration that we are referencing. - ValueDecl *D; - - /// \brief The location of the declaration name itself. - SourceLocation Loc; - - /// \brief Provides source/type location info for the declaration name - /// embedded in D. - DeclarationNameLoc DNLoc; - - size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const { - return hasQualifier() ? 1 : 0; - } - - size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { - return hasFoundDecl() ? 1 : 0; - } - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return hasTemplateKWAndArgsInfo() ? 1 : 0; - } - - /// \brief Test whether there is a distinct FoundDecl attached to the end of - /// this DRE. - bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } - - DeclRefExpr(const ASTContext &Ctx, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *D, bool RefersToEnlosingVariableOrCapture, - const DeclarationNameInfo &NameInfo, - NamedDecl *FoundD, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK); - - /// \brief Construct an empty declaration reference expression. - explicit DeclRefExpr(EmptyShell Empty) - : Expr(DeclRefExprClass, Empty) { } - - /// \brief Computes the type- and value-dependence flags for this - /// declaration reference expression. - void computeDependence(const ASTContext &C); - -public: - DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, - ExprValueKind VK, SourceLocation L, - const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), - D(D), Loc(L), DNLoc(LocInfo) { - DeclRefExprBits.HasQualifier = 0; - DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; - DeclRefExprBits.HasFoundDecl = 0; - DeclRefExprBits.HadMultipleCandidates = 0; - DeclRefExprBits.RefersToEnclosingVariableOrCapture = - RefersToEnclosingVariableOrCapture; - computeDependence(D->getASTContext()); - } - - static DeclRefExpr * - Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, - QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, - const TemplateArgumentListInfo *TemplateArgs = nullptr); - - static DeclRefExpr * - Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingVariableOrCapture, - const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, - NamedDecl *FoundD = nullptr, - const TemplateArgumentListInfo *TemplateArgs = nullptr); - - /// \brief Construct an empty declaration reference expression. - static DeclRefExpr *CreateEmpty(const ASTContext &Context, - bool HasQualifier, - bool HasFoundDecl, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); - - ValueDecl *getDecl() { return D; } - const ValueDecl *getDecl() const { return D; } - void setDecl(ValueDecl *NewD) { D = NewD; } - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); - } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - /// \brief Determine whether this declaration reference was preceded by a - /// C++ nested-name-specifier, e.g., \c N::foo. - bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } - - /// \brief If the name was qualified, retrieves the nested-name-specifier - /// that precedes the name, with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { - if (!hasQualifier()) - return NestedNameSpecifierLoc(); - return *getTrailingObjects<NestedNameSpecifierLoc>(); - } - - /// \brief If the name was qualified, retrieves the nested-name-specifier - /// that precedes the name. Otherwise, returns NULL. - NestedNameSpecifier *getQualifier() const { - return getQualifierLoc().getNestedNameSpecifier(); - } - - /// \brief Get the NamedDecl through which this reference occurred. - /// - /// This Decl may be different from the ValueDecl actually referred to in the - /// presence of using declarations, etc. It always returns non-NULL, and may - /// simple return the ValueDecl when appropriate. - - NamedDecl *getFoundDecl() { - return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; - } - - /// \brief Get the NamedDecl through which this reference occurred. - /// See non-const variant. - const NamedDecl *getFoundDecl() const { - return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; - } - - bool hasTemplateKWAndArgsInfo() const { - return DeclRefExprBits.HasTemplateKWAndArgsInfo; - } - - /// \brief Retrieve the location of the template keyword preceding - /// this name, if any. - SourceLocation getTemplateKeywordLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; - } - - /// \brief Retrieve the location of the left angle bracket starting the - /// explicit template argument list following the name, if any. - SourceLocation getLAngleLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; - } - - /// \brief Retrieve the location of the right angle bracket ending the - /// explicit template argument list following the name, if any. - SourceLocation getRAngleLoc() const { - if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; - } - - /// \brief Determines whether the name in this declaration reference - /// was preceded by the template keyword. - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - - /// \brief Determines whether this declaration reference was followed by an - /// explicit template argument list. - bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - - /// \brief Copies the template arguments (if present) into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgs()) - getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( - getTrailingObjects<TemplateArgumentLoc>(), List); - } - - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return nullptr; - - return getTrailingObjects<TemplateArgumentLoc>(); - } - - /// \brief Retrieve the number of template arguments provided as part of this - /// template-id. - unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return 0; - - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; - } - - /// \brief Returns true if this expression refers to a function that - /// was resolved from an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { - return DeclRefExprBits.HadMultipleCandidates; - } - /// \brief Sets the flag telling whether this expression refers to - /// a function that was resolved from an overloaded set having size - /// greater than 1. - void setHadMultipleCandidates(bool V = true) { - DeclRefExprBits.HadMultipleCandidates = V; - } - - /// \brief Does this DeclRefExpr refer to an enclosing local or a captured - /// variable? - bool refersToEnclosingVariableOrCapture() const { - return DeclRefExprBits.RefersToEnclosingVariableOrCapture; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DeclRefExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. -class PredefinedExpr : public Expr { -public: - enum IdentType { - Func, - Function, - LFunction, // Same as Function, but as wide string. - FuncDName, - FuncSig, - PrettyFunction, - /// \brief The same as PrettyFunction, except that the - /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual - }; - -private: - SourceLocation Loc; - IdentType Type; - Stmt *FnName; - -public: - PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, - StringLiteral *SL); - - /// \brief Construct an empty predefined expression. - explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} - - IdentType getIdentType() const { return Type; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - StringLiteral *getFunctionName(); - const StringLiteral *getFunctionName() const { - return const_cast<PredefinedExpr *>(this)->getFunctionName(); - } - - static StringRef getIdentTypeName(IdentType IT); - static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PredefinedExprClass; - } - - // Iterators - child_range children() { return child_range(&FnName, &FnName + 1); } - - friend class ASTStmtReader; -}; - -/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without -/// leaking memory. -/// -/// For large floats/integers, APFloat/APInt will allocate memory from the heap -/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator -/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with -/// the APFloat/APInt values will never get freed. APNumericStorage uses -/// ASTContext's allocator for memory allocation. -class APNumericStorage { - union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; - unsigned BitWidth; - - bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } - - APNumericStorage(const APNumericStorage &) = delete; - void operator=(const APNumericStorage &) = delete; - -protected: - APNumericStorage() : VAL(0), BitWidth(0) { } - - llvm::APInt getIntValue() const { - unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - if (NumWords > 1) - return llvm::APInt(BitWidth, NumWords, pVal); - else - return llvm::APInt(BitWidth, VAL); - } - void setIntValue(const ASTContext &C, const llvm::APInt &Val); -}; - -class APIntStorage : private APNumericStorage { -public: - llvm::APInt getValue() const { return getIntValue(); } - void setValue(const ASTContext &C, const llvm::APInt &Val) { - setIntValue(C, Val); - } -}; - -class APFloatStorage : private APNumericStorage { -public: - llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { - return llvm::APFloat(Semantics, getIntValue()); - } - void setValue(const ASTContext &C, const llvm::APFloat &Val) { - setIntValue(C, Val.bitcastToAPInt()); - } -}; - -class IntegerLiteral : public Expr, public APIntStorage { - SourceLocation Loc; - - /// \brief Construct an empty integer literal. - explicit IntegerLiteral(EmptyShell Empty) - : Expr(IntegerLiteralClass, Empty) { } - -public: - // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, - // or UnsignedLongLongTy - IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, - SourceLocation l); - - /// \brief Returns a new integer literal with value 'V' and type 'type'. - /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy, - /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V - /// \param V - the value that the returned integer literal contains. - static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V, - QualType type, SourceLocation l); - /// \brief Returns a new empty integer literal. - static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - /// \brief Retrieve the location of the literal. - SourceLocation getLocation() const { return Loc; } - - void setLocation(SourceLocation Location) { Loc = Location; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == IntegerLiteralClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -class CharacterLiteral : public Expr { -public: - enum CharacterKind { - Ascii, - Wide, - UTF16, - UTF32 - }; - -private: - unsigned Value; - SourceLocation Loc; -public: - // type should be IntTy - CharacterLiteral(unsigned value, CharacterKind kind, QualType type, - SourceLocation l) - : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(value), Loc(l) { - CharacterLiteralBits.Kind = kind; - } - - /// \brief Construct an empty character literal. - CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } - - SourceLocation getLocation() const { return Loc; } - CharacterKind getKind() const { - return static_cast<CharacterKind>(CharacterLiteralBits.Kind); - } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - unsigned getValue() const { return Value; } - - void setLocation(SourceLocation Location) { Loc = Location; } - void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; } - void setValue(unsigned Val) { Value = Val; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CharacterLiteralClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -class FloatingLiteral : public Expr, private APFloatStorage { - SourceLocation Loc; - - FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, - QualType Type, SourceLocation L); - - /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty); - -public: - static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V, - bool isexact, QualType Type, SourceLocation L); - static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty); - - llvm::APFloat getValue() const { - return APFloatStorage::getValue(getSemantics()); - } - void setValue(const ASTContext &C, const llvm::APFloat &Val) { - assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics"); - APFloatStorage::setValue(C, Val); - } - - /// Get a raw enumeration value representing the floating-point semantics of - /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. - APFloatSemantics getRawSemantics() const { - return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics); - } - - /// Set the raw enumeration value representing the floating-point semantics of - /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. - void setRawSemantics(APFloatSemantics Sem) { - FloatingLiteralBits.Semantics = Sem; - } - - /// Return the APFloat semantics this literal uses. - const llvm::fltSemantics &getSemantics() const; - - /// Set the APFloat semantics this literal uses. - void setSemantics(const llvm::fltSemantics &Sem); - - bool isExact() const { return FloatingLiteralBits.IsExact; } - void setExact(bool E) { FloatingLiteralBits.IsExact = E; } - - /// getValueAsApproximateDouble - This returns the value as an inaccurate - /// double. Note that this may cause loss of precision, but is useful for - /// debugging dumps, etc. - double getValueAsApproximateDouble() const; - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == FloatingLiteralClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// ImaginaryLiteral - We support imaginary integer and floating point literals, -/// like "1.0i". We represent these as a wrapper around FloatingLiteral and -/// IntegerLiteral classes. Instances of this class always have a Complex type -/// whose element type matches the subexpression. -/// -class ImaginaryLiteral : public Expr { - Stmt *Val; -public: - ImaginaryLiteral(Expr *val, QualType Ty) - : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Val(val) {} - - /// \brief Build an empty imaginary literal. - explicit ImaginaryLiteral(EmptyShell Empty) - : Expr(ImaginaryLiteralClass, Empty) { } - - const Expr *getSubExpr() const { return cast<Expr>(Val); } - Expr *getSubExpr() { return cast<Expr>(Val); } - void setSubExpr(Expr *E) { Val = E; } - - SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ImaginaryLiteralClass; - } - - // Iterators - child_range children() { return child_range(&Val, &Val+1); } -}; - -/// StringLiteral - This represents a string literal expression, e.g. "foo" -/// or L"bar" (wide strings). The actual string is returned by getBytes() -/// is NOT null-terminated, and the length of the string is determined by -/// calling getByteLength(). The C type for a string is always a -/// ConstantArrayType. In C++, the char type is const qualified, in C it is -/// not. -/// -/// Note that strings in C can be formed by concatenation of multiple string -/// literal pptokens in translation phase #6. This keeps track of the locations -/// of each of these pieces. -/// -/// Strings in C can also be truncated and extended by assigning into arrays, -/// e.g. with constructs like: -/// char X[2] = "foobar"; -/// In this case, getByteLength() will return 6, but the string literal will -/// have type "char[2]". -class StringLiteral : public Expr { -public: - enum StringKind { - Ascii, - Wide, - UTF8, - UTF16, - UTF32 - }; - -private: - friend class ASTStmtReader; - - union { - const char *asChar; - const uint16_t *asUInt16; - const uint32_t *asUInt32; - } StrData; - unsigned Length; - unsigned CharByteWidth : 4; - unsigned Kind : 3; - unsigned IsPascal : 1; - unsigned NumConcatenated; - SourceLocation TokLocs[1]; - - StringLiteral(QualType Ty) : - Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, - false) {} - - static int mapCharByteWidth(TargetInfo const &target,StringKind k); - -public: - /// This is the "fully general" constructor that allows representation of - /// strings formed from multiple concatenated tokens. - static StringLiteral *Create(const ASTContext &C, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, - const SourceLocation *Loc, unsigned NumStrs); - - /// Simple constructor for string literals made from one token. - static StringLiteral *Create(const ASTContext &C, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, - SourceLocation Loc) { - return Create(C, Str, Kind, Pascal, Ty, &Loc, 1); - } - - /// \brief Construct an empty string literal. - static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs); - - StringRef getString() const { - assert(CharByteWidth==1 - && "This function is used in places that assume strings use char"); - return StringRef(StrData.asChar, getByteLength()); - } - - /// Allow access to clients that need the byte representation, such as - /// ASTWriterStmt::VisitStringLiteral(). - StringRef getBytes() const { - // FIXME: StringRef may not be the right type to use as a result for this. - if (CharByteWidth == 1) - return StringRef(StrData.asChar, getByteLength()); - if (CharByteWidth == 4) - return StringRef(reinterpret_cast<const char*>(StrData.asUInt32), - getByteLength()); - assert(CharByteWidth == 2 && "unsupported CharByteWidth"); - return StringRef(reinterpret_cast<const char*>(StrData.asUInt16), - getByteLength()); - } - - void outputString(raw_ostream &OS) const; - - uint32_t getCodeUnit(size_t i) const { - assert(i < Length && "out of bounds access"); - if (CharByteWidth == 1) - return static_cast<unsigned char>(StrData.asChar[i]); - if (CharByteWidth == 4) - return StrData.asUInt32[i]; - assert(CharByteWidth == 2 && "unsupported CharByteWidth"); - return StrData.asUInt16[i]; - } - - unsigned getByteLength() const { return CharByteWidth*Length; } - unsigned getLength() const { return Length; } - unsigned getCharByteWidth() const { return CharByteWidth; } - - /// \brief Sets the string data to the given string data. - void setString(const ASTContext &C, StringRef Str, - StringKind Kind, bool IsPascal); - - StringKind getKind() const { return static_cast<StringKind>(Kind); } - - - bool isAscii() const { return Kind == Ascii; } - bool isWide() const { return Kind == Wide; } - bool isUTF8() const { return Kind == UTF8; } - bool isUTF16() const { return Kind == UTF16; } - bool isUTF32() const { return Kind == UTF32; } - bool isPascal() const { return IsPascal; } - - bool containsNonAsciiOrNull() const { - StringRef Str = getString(); - for (unsigned i = 0, e = Str.size(); i != e; ++i) - if (!isASCII(Str[i]) || !Str[i]) - return true; - return false; - } - - /// getNumConcatenated - Get the number of string literal tokens that were - /// concatenated in translation phase #6 to form this string literal. - unsigned getNumConcatenated() const { return NumConcatenated; } - - SourceLocation getStrTokenLoc(unsigned TokNum) const { - assert(TokNum < NumConcatenated && "Invalid tok number"); - return TokLocs[TokNum]; - } - void setStrTokenLoc(unsigned TokNum, SourceLocation L) { - 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, - unsigned *StartToken = nullptr, - unsigned *StartTokenByteOffset = nullptr) const; - - typedef const SourceLocation *tokloc_iterator; - tokloc_iterator tokloc_begin() const { return TokLocs; } - tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; } - - SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; } - SourceLocation getLocEnd() const LLVM_READONLY { - return TokLocs[NumConcatenated - 1]; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == StringLiteralClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This -/// AST node is only formed if full location information is requested. -class ParenExpr : public Expr { - SourceLocation L, R; - Stmt *Val; -public: - ParenExpr(SourceLocation l, SourceLocation r, Expr *val) - : Expr(ParenExprClass, val->getType(), - val->getValueKind(), val->getObjectKind(), - val->isTypeDependent(), val->isValueDependent(), - val->isInstantiationDependent(), - val->containsUnexpandedParameterPack()), - L(l), R(r), Val(val) {} - - /// \brief Construct an empty parenthesized expression. - explicit ParenExpr(EmptyShell Empty) - : Expr(ParenExprClass, Empty) { } - - const Expr *getSubExpr() const { return cast<Expr>(Val); } - Expr *getSubExpr() { return cast<Expr>(Val); } - void setSubExpr(Expr *E) { Val = E; } - - SourceLocation getLocStart() const LLVM_READONLY { return L; } - SourceLocation getLocEnd() const LLVM_READONLY { return R; } - - /// \brief Get the location of the left parentheses '('. - SourceLocation getLParen() const { return L; } - void setLParen(SourceLocation Loc) { L = Loc; } - - /// \brief Get the location of the right parentheses ')'. - SourceLocation getRParen() const { return R; } - void setRParen(SourceLocation Loc) { R = Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ParenExprClass; - } - - // Iterators - child_range children() { return child_range(&Val, &Val+1); } -}; - -/// UnaryOperator - This represents the unary-expression's (except sizeof and -/// alignof), the postinc/postdec operators from postfix-expression, and various -/// extensions. -/// -/// Notes on various nodes: -/// -/// Real/Imag - These return the real/imag part of a complex operand. If -/// applied to a non-complex value, the former returns its operand and the -/// later returns zero in the type of the operand. -/// -class UnaryOperator : public Expr { -public: - typedef UnaryOperatorKind Opcode; - -private: - unsigned Opc : 5; - SourceLocation Loc; - Stmt *Val; -public: - - 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->isInstantiationDependent() || - type->isInstantiationDependentType()), - input->containsUnexpandedParameterPack()), - Opc(opc), Loc(l), Val(input) {} - - /// \brief Build an empty unary operator. - explicit UnaryOperator(EmptyShell Empty) - : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } - - Opcode getOpcode() const { return static_cast<Opcode>(Opc); } - void setOpcode(Opcode O) { Opc = O; } - - Expr *getSubExpr() const { return cast<Expr>(Val); } - void setSubExpr(Expr *E) { Val = E; } - - /// getOperatorLoc - Return the location of the operator. - SourceLocation getOperatorLoc() const { return Loc; } - void setOperatorLoc(SourceLocation L) { Loc = L; } - - /// isPostfix - Return true if this is a postfix operation, like x++. - static bool isPostfix(Opcode Op) { - return Op == UO_PostInc || Op == UO_PostDec; - } - - /// isPrefix - Return true if this is a prefix operation, like --x. - static bool isPrefix(Opcode Op) { - return Op == UO_PreInc || Op == UO_PreDec; - } - - bool isPrefix() const { return isPrefix(getOpcode()); } - bool isPostfix() const { return isPostfix(getOpcode()); } - - static bool isIncrementOp(Opcode Op) { - return Op == UO_PreInc || Op == UO_PostInc; - } - bool isIncrementOp() const { - return isIncrementOp(getOpcode()); - } - - static bool isDecrementOp(Opcode Op) { - return Op == UO_PreDec || Op == UO_PostDec; - } - bool isDecrementOp() const { - return isDecrementOp(getOpcode()); - } - - static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; } - bool isIncrementDecrementOp() const { - return isIncrementDecrementOp(getOpcode()); - } - - static bool isArithmeticOp(Opcode Op) { - return Op >= UO_Plus && Op <= UO_LNot; - } - bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); } - - /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it - /// corresponds to, e.g. "sizeof" or "[pre]++" - static StringRef getOpcodeStr(Opcode Op); - - /// \brief Retrieve the unary opcode that corresponds to the given - /// overloaded operator. - static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); - - /// \brief Retrieve the overloaded operator kind that corresponds to - /// the given unary opcode. - static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - - SourceLocation getLocStart() const LLVM_READONLY { - return isPostfix() ? Val->getLocStart() : Loc; - } - SourceLocation getLocEnd() const LLVM_READONLY { - return isPostfix() ? Loc : Val->getLocEnd(); - } - SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnaryOperatorClass; - } - - // Iterators - child_range children() { return child_range(&Val, &Val+1); } -}; - -/// Helper class for OffsetOfExpr. - -// __builtin_offsetof(type, identifier(.identifier|[expr])*) -class OffsetOfNode { -public: - /// \brief The kind of offsetof node we have. - enum Kind { - /// \brief An index into an array. - Array = 0x00, - /// \brief A field. - Field = 0x01, - /// \brief A field in a dependent type, known only by its name. - Identifier = 0x02, - /// \brief An implicit indirection through a C++ base class, when the - /// field found is in a base class. - Base = 0x03 - }; - -private: - enum { MaskBits = 2, Mask = 0x03 }; - - /// \brief The source range that covers this part of the designator. - SourceRange Range; - - /// \brief The data describing the designator, which comes in three - /// different forms, depending on the lower two bits. - /// - An unsigned index into the array of Expr*'s stored after this node - /// in memory, for [constant-expression] designators. - /// - A FieldDecl*, for references to a known field. - /// - An IdentifierInfo*, for references to a field with a given name - /// when the class type is dependent. - /// - A CXXBaseSpecifier*, for references that look at a field in a - /// base class. - uintptr_t Data; - -public: - /// \brief Create an offsetof node that refers to an array element. - OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, - SourceLocation RBracketLoc) - : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {} - - /// \brief Create an offsetof node that refers to a field. - OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) - : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), - Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {} - - /// \brief Create an offsetof node that refers to an identifier. - OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, - SourceLocation NameLoc) - : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), - Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {} - - /// \brief Create an offsetof node that refers into a C++ base class. - explicit OffsetOfNode(const CXXBaseSpecifier *Base) - : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} - - /// \brief Determine what kind of offsetof node this is. - Kind getKind() const { return static_cast<Kind>(Data & Mask); } - - /// \brief For an array element node, returns the index into the array - /// of expressions. - unsigned getArrayExprIndex() const { - assert(getKind() == Array); - return Data >> 2; - } - - /// \brief For a field offsetof node, returns the field. - FieldDecl *getField() const { - assert(getKind() == Field); - return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); - } - - /// \brief For a field or identifier offsetof node, returns the name of - /// the field. - IdentifierInfo *getFieldName() const; - - /// \brief For a base class node, returns the base specifier. - CXXBaseSpecifier *getBase() const { - assert(getKind() == Base); - return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); - } - - /// \brief Retrieve the source range that covers this offsetof node. - /// - /// For an array element node, the source range contains the locations of - /// the square brackets. For a field or identifier node, the source range - /// contains the location of the period (if there is one) and the - /// identifier. - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } -}; - -/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form -/// offsetof(record-type, member-designator). For example, given: -/// @code -/// struct S { -/// float f; -/// double d; -/// }; -/// struct T { -/// int i; -/// struct S s[10]; -/// }; -/// @endcode -/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). - -class OffsetOfExpr final - : public Expr, - private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> { - SourceLocation OperatorLoc, RParenLoc; - // Base type; - TypeSourceInfo *TSInfo; - // Number of sub-components (i.e. instances of OffsetOfNode). - unsigned NumComps; - // Number of sub-expressions (i.e. array subscript expressions). - unsigned NumExprs; - - size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const { - return NumComps; - } - - OffsetOfExpr(const ASTContext &C, QualType type, - SourceLocation OperatorLoc, TypeSourceInfo *tsi, - ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs, - SourceLocation RParenLoc); - - explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) - : Expr(OffsetOfExprClass, EmptyShell()), - TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {} - -public: - - static OffsetOfExpr *Create(const ASTContext &C, QualType type, - SourceLocation OperatorLoc, TypeSourceInfo *tsi, - ArrayRef<OffsetOfNode> comps, - ArrayRef<Expr*> exprs, SourceLocation RParenLoc); - - static OffsetOfExpr *CreateEmpty(const ASTContext &C, - unsigned NumComps, unsigned NumExprs); - - /// getOperatorLoc - Return the location of the operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } - - /// \brief Return the location of the right parentheses. - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation R) { RParenLoc = R; } - - TypeSourceInfo *getTypeSourceInfo() const { - return TSInfo; - } - void setTypeSourceInfo(TypeSourceInfo *tsi) { - TSInfo = tsi; - } - - const OffsetOfNode &getComponent(unsigned Idx) const { - assert(Idx < NumComps && "Subscript out of range"); - return getTrailingObjects<OffsetOfNode>()[Idx]; - } - - void setComponent(unsigned Idx, OffsetOfNode ON) { - assert(Idx < NumComps && "Subscript out of range"); - getTrailingObjects<OffsetOfNode>()[Idx] = ON; - } - - unsigned getNumComponents() const { - return NumComps; - } - - Expr* getIndexExpr(unsigned Idx) { - assert(Idx < NumExprs && "Subscript out of range"); - return getTrailingObjects<Expr *>()[Idx]; - } - - const Expr *getIndexExpr(unsigned Idx) const { - assert(Idx < NumExprs && "Subscript out of range"); - return getTrailingObjects<Expr *>()[Idx]; - } - - void setIndexExpr(unsigned Idx, Expr* E) { - assert(Idx < NumComps && "Subscript out of range"); - getTrailingObjects<Expr *>()[Idx] = E; - } - - unsigned getNumExpressions() const { - return NumExprs; - } - - SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OffsetOfExprClass; - } - - // Iterators - child_range children() { - Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); - return child_range(begin, begin + NumExprs); - } - friend TrailingObjects; -}; - -/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) -/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and -/// vec_step (OpenCL 1.1 6.11.12). -class UnaryExprOrTypeTraitExpr : public Expr { - union { - TypeSourceInfo *Ty; - Stmt *Ex; - } Argument; - SourceLocation OpLoc, RParenLoc; - -public: - UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(UnaryExprOrTypeTraitExprClass, 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()->isInstantiationDependentType(), - TInfo->getType()->containsUnexpandedParameterPack()), - OpLoc(op), RParenLoc(rp) { - UnaryExprOrTypeTraitExprBits.Kind = ExprKind; - UnaryExprOrTypeTraitExprBits.IsType = true; - Argument.Ty = TInfo; - } - - UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, - QualType resultType, SourceLocation op, - SourceLocation rp); - - /// \brief Construct an empty sizeof/alignof expression. - explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) - : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } - - UnaryExprOrTypeTrait getKind() const { - return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind); - } - void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;} - - bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; } - QualType getArgumentType() const { - return getArgumentTypeInfo()->getType(); - } - TypeSourceInfo *getArgumentTypeInfo() const { - assert(isArgumentType() && "calling getArgumentType() when arg is expr"); - return Argument.Ty; - } - Expr *getArgumentExpr() { - assert(!isArgumentType() && "calling getArgumentExpr() when arg is type"); - return static_cast<Expr*>(Argument.Ex); - } - const Expr *getArgumentExpr() const { - return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); - } - - void setArgument(Expr *E) { - Argument.Ex = E; - UnaryExprOrTypeTraitExprBits.IsType = false; - } - void setArgument(TypeSourceInfo *TInfo) { - Argument.Ty = TInfo; - UnaryExprOrTypeTraitExprBits.IsType = true; - } - - /// Gets the argument type, or the type of the argument expression, whichever - /// is appropriate. - QualType getTypeOfArgument() const { - return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType(); - } - - SourceLocation getOperatorLoc() const { return OpLoc; } - void setOperatorLoc(SourceLocation L) { OpLoc = L; } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; - } - - // Iterators - child_range children(); -}; - -//===----------------------------------------------------------------------===// -// Postfix Operators. -//===----------------------------------------------------------------------===// - -/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. -class ArraySubscriptExpr : public Expr { - enum { LHS, RHS, END_EXPR=2 }; - Stmt* SubExprs[END_EXPR]; - SourceLocation RBracketLoc; -public: - ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation rbracketloc) - : Expr(ArraySubscriptExprClass, t, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - RBracketLoc(rbracketloc) { - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } - - /// \brief Create an empty array subscript expression. - explicit ArraySubscriptExpr(EmptyShell Shell) - : Expr(ArraySubscriptExprClass, Shell) { } - - /// An array access can be written A[4] or 4[A] (both are equivalent). - /// - getBase() and getIdx() always present the normalized view: A[4]. - /// In this case getBase() returns "A" and getIdx() returns "4". - /// - getLHS() and getRHS() present the syntactic view. e.g. for - /// 4[A] getLHS() returns "4". - /// Note: Because vector element access is also written A[4] we must - /// predicate the format conversion in getBase and getIdx only on the - /// the type of the RHS, as it is possible for the LHS to be a vector of - /// integer type - Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); } - const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } - void setLHS(Expr *E) { SubExprs[LHS] = E; } - - Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); } - const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - void setRHS(Expr *E) { SubExprs[RHS] = E; } - - Expr *getBase() { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); - } - - const Expr *getBase() const { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); - } - - Expr *getIdx() { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); - } - - const Expr *getIdx() const { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getLHS()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } - - SourceLocation getRBracketLoc() const { return RBracketLoc; } - void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - - SourceLocation getExprLoc() const LLVM_READONLY { - return getBase()->getExprLoc(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ArraySubscriptExprClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } -}; - -/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). -/// CallExpr itself represents a normal function call, e.g., "f(x, 2)", -/// while its subclasses may represent alternative syntax that (semantically) -/// results in a function call. For example, CXXOperatorCallExpr is -/// a subclass for overloaded operator calls that use operator syntax, e.g., -/// "str1 + str2" to resolve to a function call. -class CallExpr : public Expr { - enum { FN=0, PREARGS_START=1 }; - Stmt **SubExprs; - unsigned NumArgs; - SourceLocation RParenLoc; - -protected: - // These versions of the constructor are for derived classes. - CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, - ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation rparenloc); - CallExpr(const 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(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc); - - /// \brief Build an empty call expression. - CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty); - - const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } - Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } - void setCallee(Expr *F) { SubExprs[FN] = F; } - - Decl *getCalleeDecl(); - const Decl *getCalleeDecl() const { - return const_cast<CallExpr*>(this)->getCalleeDecl(); - } - - /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. - FunctionDecl *getDirectCallee(); - const FunctionDecl *getDirectCallee() const { - return const_cast<CallExpr*>(this)->getDirectCallee(); - } - - /// getNumArgs - Return the number of actual arguments to this call. - /// - unsigned getNumArgs() const { return NumArgs; } - - /// \brief Retrieve the call arguments. - Expr **getArgs() { - return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); - } - const Expr *const *getArgs() const { - 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_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); - } - const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast_or_null<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+getNumPreArgs()+PREARGS_START] = ArgExpr; - } - - /// setNumArgs - This changes the number of arguments present in this call. - /// Any orphaned expressions are deleted by this, and any new operands are set - /// to null. - void setNumArgs(const ASTContext& C, unsigned NumArgs); - - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - typedef llvm::iterator_range<arg_iterator> arg_range; - typedef llvm::iterator_range<const_arg_iterator> arg_const_range; - - arg_range arguments() { return arg_range(arg_begin(), arg_end()); } - arg_const_range arguments() const { - return arg_const_range(arg_begin(), arg_end()); - } - - 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(); - } - - /// This method provides fast access to all the subexpressions of - /// a CallExpr without going through the slower virtual child_iterator - /// interface. This provides efficient reverse iteration of the - /// subexpressions. This is currently used for CFG construction. - ArrayRef<Stmt*> getRawSubExprs() { - return llvm::makeArrayRef(SubExprs, - getNumPreArgs() + PREARGS_START + getNumArgs()); - } - - /// getNumCommas - Return the number of commas that must have been present in - /// this function call. - unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } - - /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID - /// of the callee. If not, return 0. - unsigned getBuiltinCallee() const; - - /// \brief Returns \c true if this is a call to a builtin which does not - /// evaluate side-effects within its arguments. - bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) 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 - /// type. - QualType getCallReturnType(const ASTContext &Ctx) const; - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() >= firstCallExprConstant && - T->getStmtClass() <= lastCallExprConstant; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); - } -}; - -/// Extra data stored in some MemberExpr objects. -struct MemberExprNameQualifier { - /// \brief The nested-name-specifier that qualifies the name, including - /// source-location information. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The DeclAccessPair through which the MemberDecl was found due to - /// name qualifiers. - DeclAccessPair FoundDecl; -}; - -/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. -/// -class MemberExpr final - : public Expr, - private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier, - ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { - /// Base - the expression for the base pointer or structure references. In - /// X.F, this is "X". - Stmt *Base; - - /// MemberDecl - This is the decl being referenced by the field/member name. - /// In X.F, this is the decl referenced by F. - ValueDecl *MemberDecl; - - /// MemberDNLoc - Provides source/type location info for the - /// declaration name embedded in MemberDecl. - DeclarationNameLoc MemberDNLoc; - - /// MemberLoc - This is the location of the member name. - SourceLocation MemberLoc; - - /// This is the location of the -> or . in the expression. - SourceLocation OperatorLoc; - - /// IsArrow - True if this is "X->F", false if this is "X.F". - bool IsArrow : 1; - - /// \brief True if this member expression used a nested-name-specifier to - /// refer to the member, e.g., "x->Base::f", or found its member via a using - /// declaration. When true, a MemberExprNameQualifier - /// structure is allocated immediately after the MemberExpr. - bool HasQualifierOrFoundDecl : 1; - - /// \brief True if this member expression specified a template keyword - /// and/or a template argument list explicitly, e.g., x->f<int>, - /// x->template f, x->template f<int>. - /// When true, an ASTTemplateKWAndArgsInfo structure and its - /// TemplateArguments (if any) are present. - bool HasTemplateKWAndArgsInfo : 1; - - /// \brief True if this member expression refers to a method that - /// was resolved from an overloaded set having size greater than 1. - bool HadMultipleCandidates : 1; - - size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const { - return HasQualifierOrFoundDecl ? 1 : 0; - } - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - -public: - MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, - ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo, - QualType ty, ExprValueKind VK, ExprObjectKind OK) - : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), - base->isValueDependent(), base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), - MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc), - IsArrow(isarrow), HasQualifierOrFoundDecl(false), - HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { - assert(memberdecl->getDeclName() == NameInfo.getName()); - } - - // NOTE: this constructor should be used only when it is known that - // the member name can not provide additional syntactic info - // (i.e., source locations for C++ operator names or type source info - // for constructors, destructors and conversion operators). - MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, - ValueDecl *memberdecl, SourceLocation l, QualType ty, - ExprValueKind VK, ExprObjectKind OK) - : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), - base->isValueDependent(), base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), - OperatorLoc(operatorloc), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), - HadMultipleCandidates(false) {} - - static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *memberdecl, - DeclAccessPair founddecl, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *targs, QualType ty, - ExprValueKind VK, ExprObjectKind OK); - - void setBase(Expr *E) { Base = E; } - Expr *getBase() const { return cast<Expr>(Base); } - - /// \brief Retrieve the member declaration to which this expression refers. - /// - /// The returned declaration will either be a FieldDecl or (in C++) - /// a CXXMethodDecl. - ValueDecl *getMemberDecl() const { return MemberDecl; } - void setMemberDecl(ValueDecl *D) { MemberDecl = D; } - - /// \brief Retrieves the declaration found by lookup. - DeclAccessPair getFoundDecl() const { - if (!HasQualifierOrFoundDecl) - return DeclAccessPair::make(getMemberDecl(), - getMemberDecl()->getAccess()); - return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; - } - - /// \brief Determines whether this member expression actually had - /// a C++ nested-name-specifier prior to the name of the member, e.g., - /// x->Base::foo. - bool hasQualifier() const { return getQualifier() != nullptr; } - - /// \brief If the member name was qualified, retrieves the - /// nested-name-specifier that precedes the member name, with source-location - /// information. - NestedNameSpecifierLoc getQualifierLoc() const { - if (!HasQualifierOrFoundDecl) - return NestedNameSpecifierLoc(); - - return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; - } - - /// \brief If the member name was qualified, retrieves the - /// nested-name-specifier that precedes the member name. Otherwise, returns - /// NULL. - NestedNameSpecifier *getQualifier() const { - return getQualifierLoc().getNestedNameSpecifier(); - } - - /// \brief Retrieve the location of the template keyword preceding - /// the member name, if any. - SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; - } - - /// \brief Retrieve the location of the left angle bracket starting the - /// explicit template argument list following the member name, if any. - SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; - } - - /// \brief Retrieve the location of the right angle bracket ending the - /// explicit template argument list following the member name, if any. - SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; - } - - /// Determines whether the member name was preceded by the template keyword. - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - - /// \brief Determines whether the member name was followed by an - /// explicit template argument list. - bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - - /// \brief Copies the template arguments (if present) into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgs()) - getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( - getTrailingObjects<TemplateArgumentLoc>(), List); - } - - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return nullptr; - - return getTrailingObjects<TemplateArgumentLoc>(); - } - - /// \brief Retrieve the number of template arguments provided as part of this - /// template-id. - unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return 0; - - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; - } - - /// \brief Retrieve the member declaration name info. - DeclarationNameInfo getMemberNameInfo() const { - return DeclarationNameInfo(MemberDecl->getDeclName(), - MemberLoc, MemberDNLoc); - } - - SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; } - - bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } - - /// getMemberLoc - Return the location of the "member", in X->F, it is the - /// location of 'F'. - SourceLocation getMemberLoc() const { return MemberLoc; } - void setMemberLoc(SourceLocation L) { MemberLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } - - /// \brief Determine whether the base of this explicit is implicit. - bool isImplicitAccess() const { - return getBase() && getBase()->isImplicitCXXThis(); - } - - /// \brief Returns true if this member expression refers to a method that - /// was resolved from an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { - return HadMultipleCandidates; - } - /// \brief Sets the flag telling whether this expression refers to - /// a method that was resolved from an overloaded set having size - /// greater than 1. - void setHadMultipleCandidates(bool V = true) { - HadMultipleCandidates = V; - } - - /// \brief Returns true if virtual dispatch is performed. - /// If the member access is fully qualified, (i.e. X::f()), virtual - /// dispatching is not performed. In -fapple-kext mode qualified - /// calls to virtual method will still go through the vtable. - bool performsVirtualDispatch(const LangOptions &LO) const { - return LO.AppleKext || !hasQualifier(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == MemberExprClass; - } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } - - friend TrailingObjects; - friend class ASTReader; - friend class ASTStmtWriter; -}; - -/// CompoundLiteralExpr - [C99 6.5.2.5] -/// -class CompoundLiteralExpr : public Expr { - /// LParenLoc - If non-null, this is the location of the left paren in a - /// compound literal like "(int){4}". This can be null if this is a - /// synthesized compound expression. - SourceLocation LParenLoc; - - /// The type as written. This can be an incomplete array type, in - /// which case the actual expression type will be different. - /// The int part of the pair stores whether this expr is file scope. - llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope; - Stmt *Init; -public: - CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, - QualType T, ExprValueKind VK, Expr *init, bool fileScope) - : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, - tinfo->getType()->isDependentType(), - init->isValueDependent(), - (init->isInstantiationDependent() || - tinfo->getType()->isInstantiationDependentType()), - init->containsUnexpandedParameterPack()), - LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} - - /// \brief Construct an empty compound literal. - explicit CompoundLiteralExpr(EmptyShell Empty) - : Expr(CompoundLiteralExprClass, Empty) { } - - const Expr *getInitializer() const { return cast<Expr>(Init); } - Expr *getInitializer() { return cast<Expr>(Init); } - void setInitializer(Expr *E) { Init = E; } - - bool isFileScope() const { return TInfoAndScope.getInt(); } - void setFileScope(bool FS) { TInfoAndScope.setInt(FS); } - - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - - TypeSourceInfo *getTypeSourceInfo() const { - return TInfoAndScope.getPointer(); - } - void setTypeSourceInfo(TypeSourceInfo *tinfo) { - TInfoAndScope.setPointer(tinfo); - } - - SourceLocation getLocStart() const LLVM_READONLY { - // FIXME: Init should never be null. - if (!Init) - return SourceLocation(); - if (LParenLoc.isInvalid()) - return Init->getLocStart(); - return LParenLoc; - } - SourceLocation getLocEnd() const LLVM_READONLY { - // FIXME: Init should never be null. - if (!Init) - return SourceLocation(); - return Init->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CompoundLiteralExprClass; - } - - // Iterators - child_range children() { return child_range(&Init, &Init+1); } -}; - -/// CastExpr - Base class for type casts, including both implicit -/// casts (ImplicitCastExpr) and explicit casts that have some -/// representation in the source code (ExplicitCastExpr's derived -/// classes). -class CastExpr : public Expr { -private: - Stmt *Op; - - bool CastConsistency() const; - - const CXXBaseSpecifier * const *path_buffer() const { - return const_cast<CastExpr*>(this)->path_buffer(); - } - CXXBaseSpecifier **path_buffer(); - - void setBasePathSize(unsigned basePathSize) { - CastExprBits.BasePathSize = basePathSize; - assert(CastExprBits.BasePathSize == basePathSize && - "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); - } - -protected: - 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()), - (ty->isInstantiationDependentType() || - (op && op->isInstantiationDependent())), - // An implicit cast expression doesn't (lexically) contain an - // unexpanded pack, even if its target type does. - ((SC != ImplicitCastExprClass && - ty->containsUnexpandedParameterPack()) || - (op && op->containsUnexpandedParameterPack()))), - Op(op) { - assert(kind != CK_Invalid && "creating cast with invalid cast kind"); - CastExprBits.Kind = kind; - setBasePathSize(BasePathSize); - assert(CastConsistency()); - } - - /// \brief Construct an empty cast. - CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) - : Expr(SC, Empty) { - setBasePathSize(BasePathSize); - } - -public: - CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } - void setCastKind(CastKind K) { CastExprBits.Kind = K; } - const char *getCastKindName() const; - - Expr *getSubExpr() { return cast<Expr>(Op); } - const Expr *getSubExpr() const { return cast<Expr>(Op); } - void setSubExpr(Expr *E) { Op = E; } - - /// \brief Retrieve the cast subexpression as it was written in the source - /// code, looking through any implicit casts or other intermediate nodes - /// introduced by semantic analysis. - Expr *getSubExprAsWritten(); - const Expr *getSubExprAsWritten() const { - return const_cast<CastExpr *>(this)->getSubExprAsWritten(); - } - - typedef CXXBaseSpecifier **path_iterator; - typedef const CXXBaseSpecifier * const *path_const_iterator; - 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(); } - path_const_iterator path_end() const { return path_buffer() + path_size(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() >= firstCastExprConstant && - T->getStmtClass() <= lastCastExprConstant; - } - - // Iterators - child_range children() { return child_range(&Op, &Op+1); } -}; - -/// ImplicitCastExpr - Allows us to explicitly represent implicit type -/// conversions, which have no direct representation in the original -/// source code. For example: converting T[]->T*, void f()->void -/// (*f)(), float->double, short->int, etc. -/// -/// In C, implicit casts always produce rvalues. However, in C++, an -/// implicit cast whose result is being bound to a reference will be -/// an lvalue or xvalue. For example: -/// -/// @code -/// class Base { }; -/// class Derived : public Base { }; -/// Derived &&ref(); -/// void f(Derived d) { -/// Base& b = d; // initializer is an ImplicitCastExpr -/// // to an lvalue of type Base -/// Base&& r = ref(); // initializer is an ImplicitCastExpr -/// // to an xvalue of type Base -/// } -/// @endcode -class ImplicitCastExpr final - : public CastExpr, - private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { -private: - ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, - unsigned BasePathLength, ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { - } - - /// \brief Construct an empty implicit cast. - explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) - : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } - -public: - enum OnStack_t { OnStack }; - ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, - ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { - } - - static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, - CastKind Kind, Expr *Operand, - const CXXCastPath *BasePath, - ExprValueKind Cat); - - static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); - - SourceLocation getLocStart() const LLVM_READONLY { - return getSubExpr()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSubExpr()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ImplicitCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -inline Expr *Expr::IgnoreImpCasts() { - Expr *e = this; - while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) - e = ice->getSubExpr(); - return e; -} - -/// ExplicitCastExpr - An explicit cast written in the source -/// code. -/// -/// This class is effectively an abstract class, because it provides -/// the basic representation of an explicitly-written cast without -/// specifying which kind of cast (C cast, functional cast, static -/// cast, etc.) was written; specific derived classes represent the -/// particular style of cast and its location information. -/// -/// Unlike implicit casts, explicit cast nodes have two different -/// types: the type that was written into the source code, and the -/// actual type of the expression as determined by semantic -/// analysis. These types may differ slightly. For example, in C++ one -/// can cast to a reference type, which indicates that the resulting -/// expression will be an lvalue or xvalue. The reference type, however, -/// will not be used as the type of the expression. -class ExplicitCastExpr : public CastExpr { - /// TInfo - Source type info for the (written) type - /// this expression is casting to. - TypeSourceInfo *TInfo; - -protected: - 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) - : CastExpr(SC, Shell, PathSize) { } - -public: - /// getTypeInfoAsWritten - Returns the type source info for the type - /// that this expression is casting to. - TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; } - void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; } - - /// getTypeAsWritten - Returns the type that this expression is - /// casting to, as written in the source code. - QualType getTypeAsWritten() const { return TInfo->getType(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() >= firstExplicitCastExprConstant && - T->getStmtClass() <= lastExplicitCastExprConstant; - } -}; - -/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style -/// cast in C++ (C++ [expr.cast]), which uses the syntax -/// (Type)expr. For example: @c (int)f. -class CStyleCastExpr final - : public ExplicitCastExpr, - private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { - SourceLocation LPLoc; // the location of the left paren - SourceLocation RPLoc; // the location of the right paren - - CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op, - unsigned PathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation r) - : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, - writtenTy), LPLoc(l), RPLoc(r) {} - - /// \brief Construct an empty C-style explicit cast. - explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } - -public: - static CStyleCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind K, - Expr *Op, const CXXCastPath *BasePath, - TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation R); - - static CStyleCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); - - SourceLocation getLParenLoc() const { return LPLoc; } - void setLParenLoc(SourceLocation L) { LPLoc = L; } - - SourceLocation getRParenLoc() const { return RPLoc; } - void setRParenLoc(SourceLocation L) { RPLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSubExpr()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CStyleCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// \brief A builtin binary operation expression such as "x + y" or "x <= y". -/// -/// This expression node kind describes a builtin binary operation, -/// such as "x + y" for integer values "x" and "y". The operands will -/// already have been converted to appropriate types (e.g., by -/// performing promotions or conversions). -/// -/// In C++, where operators may be overloaded, a different kind of -/// expression node (CXXOperatorCallExpr) is used to express the -/// invocation of an overloaded operator with operator syntax. Within -/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is -/// used to store an expression "x + y" depends on the subexpressions -/// for x and y. If neither x or y is type-dependent, and the "+" -/// operator resolves to a built-in operation, BinaryOperator will be -/// used to express the computation (x and y may still be -/// value-dependent). If either x or y is type-dependent, or if the -/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will -/// be used to express the computation. -class BinaryOperator : public Expr { -public: - typedef BinaryOperatorKind Opcode; - -private: - unsigned Opc : 6; - - // Records the FP_CONTRACT pragma status at the point that this binary - // operator was parsed. This bit is only meaningful for operations on - // floating point types. For all other types it should default to - // false. - unsigned FPContractable : 1; - SourceLocation OpLoc; - - enum { LHS, RHS, END_EXPR }; - Stmt* SubExprs[END_EXPR]; -public: - - BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable) - : Expr(BinaryOperatorClass, ResTy, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - assert(!isCompoundAssignmentOp() && - "Use CompoundAssignOperator for compound assignments"); - } - - /// \brief Construct an empty binary operator. - explicit BinaryOperator(EmptyShell Empty) - : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } - - SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; } - SourceLocation getOperatorLoc() const { return OpLoc; } - void setOperatorLoc(SourceLocation L) { OpLoc = L; } - - Opcode getOpcode() const { return static_cast<Opcode>(Opc); } - void setOpcode(Opcode O) { Opc = O; } - - Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } - void setLHS(Expr *E) { SubExprs[LHS] = E; } - Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - void setRHS(Expr *E) { SubExprs[RHS] = E; } - - SourceLocation getLocStart() const LLVM_READONLY { - return getLHS()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getRHS()->getLocEnd(); - } - - /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it - /// corresponds to, e.g. "<<=". - static StringRef getOpcodeStr(Opcode Op); - - StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); } - - /// \brief Retrieve the binary opcode that corresponds to the given - /// overloaded operator. - static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); - - /// \brief Retrieve the overloaded operator kind that corresponds to - /// the given binary opcode. - static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - - /// predicates to categorize the respective opcodes. - bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; } - static bool isMultiplicativeOp(Opcode Opc) { - return Opc >= BO_Mul && Opc <= BO_Rem; - } - bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); } - static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } - bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } - static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; } - bool isShiftOp() const { return isShiftOp(getOpcode()); } - - static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; } - bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); } - - static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; } - bool isRelationalOp() const { return isRelationalOp(getOpcode()); } - - static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; } - bool isEqualityOp() const { return isEqualityOp(getOpcode()); } - - static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } - bool isComparisonOp() const { return isComparisonOp(getOpcode()); } - - static Opcode negateComparisonOp(Opcode Opc) { - switch (Opc) { - default: - llvm_unreachable("Not a comparsion operator."); - case BO_LT: return BO_GE; - case BO_GT: return BO_LE; - case BO_LE: return BO_GT; - case BO_GE: return BO_LT; - case BO_EQ: return BO_NE; - case BO_NE: return BO_EQ; - } - } - - static Opcode reverseComparisonOp(Opcode Opc) { - switch (Opc) { - default: - llvm_unreachable("Not a comparsion operator."); - case BO_LT: return BO_GT; - case BO_GT: return BO_LT; - case BO_LE: return BO_GE; - case BO_GE: return BO_LE; - case BO_EQ: - case BO_NE: - return Opc; - } - } - - static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } - bool isLogicalOp() const { return isLogicalOp(getOpcode()); } - - 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 isCompoundAssignmentOp() const { - return isCompoundAssignmentOp(getOpcode()); - } - static Opcode getOpForCompoundAssignment(Opcode Opc) { - assert(isCompoundAssignmentOp(Opc)); - if (Opc >= BO_AndAssign) - return Opcode(unsigned(Opc) - BO_AndAssign + BO_And); - else - return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul); - } - - 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 && - S->getStmtClass() <= lastBinaryOperatorConstant; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } - - // Set the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } - - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - bool isFPContractable() const { return FPContractable; } - -protected: - BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable, bool dead2) - : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } - - BinaryOperator(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Opc(BO_MulAssign) { } -}; - -/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep -/// track of the type the operation is performed in. Due to the semantics of -/// these operators, the operands are promoted, the arithmetic performed, an -/// implicit conversion back to the result type done, then the assignment takes -/// place. This captures the intermediate type which the computation is done -/// in. -class CompoundAssignOperator : public BinaryOperator { - QualType ComputationLHSType; - QualType ComputationResultType; -public: - CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, - ExprValueKind VK, ExprObjectKind OK, - QualType CompLHSType, QualType CompResultType, - SourceLocation OpLoc, bool fpContractable) - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable, - true), - ComputationLHSType(CompLHSType), - ComputationResultType(CompResultType) { - assert(isCompoundAssignmentOp() && - "Only should be used for compound assignments"); - } - - /// \brief Build an empty compound assignment operator expression. - explicit CompoundAssignOperator(EmptyShell Empty) - : BinaryOperator(CompoundAssignOperatorClass, Empty) { } - - // The two computation types are the type the LHS is converted - // to for the computation and the type of the result; the two are - // distinct in a few cases (specifically, int+=ptr and ptr-=ptr). - QualType getComputationLHSType() const { return ComputationLHSType; } - void setComputationLHSType(QualType T) { ComputationLHSType = T; } - - QualType getComputationResultType() const { return ComputationResultType; } - void setComputationResultType(QualType T) { ComputationResultType = T; } - - static bool classof(const Stmt *S) { - return S->getStmtClass() == CompoundAssignOperatorClass; - } -}; - -/// 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 ID, - bool ContainsUnexpandedParameterPack, - SourceLocation qloc, - SourceLocation cloc) - : Expr(SC, T, VK, OK, TD, VD, ID, 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; - } -}; - -/// 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. - - friend class ASTStmtReader; -public: - ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - 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->isTypeDependent() || rhs->isTypeDependent()), - (cond->isValueDependent() || lhs->isValueDependent() || - rhs->isValueDependent()), - (cond->isInstantiationDependent() || - lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (cond->containsUnexpandedParameterPack() || - lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack()), - QLoc, CLoc) { - SubExprs[COND] = cond; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } - - /// \brief Build an empty conditional operator. - explicit ConditionalOperator(EmptyShell Empty) - : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } - - // getCond - Return the expression representing the condition for - // the ?: operator. - Expr *getCond() const { return cast<Expr>(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. - Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - - Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } - Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - - SourceLocation getLocStart() const LLVM_READONLY { - return getCond()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getRHS()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ConditionalOperatorClass; - } - - // Iterators - 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->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (common->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack()), - qloc, cloc), - OpaqueValue(opaqueValue) { - SubExprs[COMMON] = common; - SubExprs[COND] = cond; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); - } - - /// \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]); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getCommon()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getFalseExpr()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BinaryConditionalOperatorClass; - } - - // 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; - LabelDecl *Label; -public: - AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L, - QualType t) - : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false, - false), - AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} - - /// \brief Build an empty address of a label expression. - explicit AddrLabelExpr(EmptyShell Empty) - : Expr(AddrLabelExprClass, Empty) { } - - SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; } - void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; } - SourceLocation getLabelLoc() const { return LabelLoc; } - void setLabelLoc(SourceLocation L) { LabelLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; } - - LabelDecl *getLabel() const { return Label; } - void setLabel(LabelDecl *L) { Label = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == AddrLabelExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// 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; -public: - // FIXME: Does type-dependence need to be computed differently? - // FIXME: Do we need to compute instantiation instantiation-dependence for - // statements? (ugh!) - StmtExpr(CompoundStmt *substmt, QualType T, - SourceLocation lp, SourceLocation rp) : - Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, - T->isDependentType(), false, false, false), - SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } - - /// \brief Build an empty statement expression. - explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } - - CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); } - const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } - void setSubStmt(CompoundStmt *S) { SubStmt = S; } - - SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == StmtExprClass; - } - - // Iterators - child_range children() { return child_range(&SubStmt, &SubStmt+1); } -}; - -/// ShuffleVectorExpr - clang-specific builtin-in function -/// __builtin_shufflevector. -/// This AST node represents a operator that does a constant -/// shuffle, similar to LLVM's shufflevector instruction. It takes -/// two vectors and a variable number of constant indices, -/// and returns the appropriately shuffled vector. -class ShuffleVectorExpr : public Expr { - SourceLocation BuiltinLoc, RParenLoc; - - // SubExprs - the list of values passed to the __builtin_shufflevector - // function. The first two are vectors, and the rest are constant - // indices. The number of values in this list is always - // 2+the number of indices in the vector type. - Stmt **SubExprs; - unsigned NumExprs; - -public: - ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type, - SourceLocation BLoc, SourceLocation RP); - - /// \brief Build an empty vector-shuffle expression. - explicit ShuffleVectorExpr(EmptyShell Empty) - : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { } - - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ShuffleVectorExprClass; - } - - /// getNumSubExprs - Return the size of the SubExprs array. This includes the - /// constant expression, the actual arguments passed in, and the function - /// pointers. - unsigned getNumSubExprs() const { return NumExprs; } - - /// \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!"); - return cast<Expr>(SubExprs[Index]); - } - const Expr *getExpr(unsigned Index) const { - assert((Index < NumExprs) && "Arg access out of range!"); - return cast<Expr>(SubExprs[Index]); - } - - void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs); - - llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const { - assert((N < NumExprs - 2) && "Shuffle idx out of range!"); - return getExpr(N+2)->EvaluateKnownConstInt(Ctx); - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+NumExprs); - } -}; - -/// ConvertVectorExpr - Clang builtin function __builtin_convertvector -/// This AST node provides support for converting a vector type to another -/// vector type of the same arity. -class ConvertVectorExpr : public Expr { -private: - Stmt *SrcExpr; - TypeSourceInfo *TInfo; - SourceLocation BuiltinLoc, RParenLoc; - - friend class ASTReader; - friend class ASTStmtReader; - explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {} - -public: - ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(ConvertVectorExprClass, DstType, VK, OK, - DstType->isDependentType(), - DstType->isDependentType() || SrcExpr->isValueDependent(), - (DstType->isInstantiationDependentType() || - SrcExpr->isInstantiationDependent()), - (DstType->containsUnexpandedParameterPack() || - SrcExpr->containsUnexpandedParameterPack())), - SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} - - /// getSrcExpr - Return the Expr to be converted. - Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } - - /// getTypeSourceInfo - Return the destination type. - TypeSourceInfo *getTypeSourceInfo() const { - return TInfo; - } - void setTypeSourceInfo(TypeSourceInfo *ti) { - TInfo = ti; - } - - /// getBuiltinLoc - Return the location of the __builtin_convertvector token. - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - - /// getRParenLoc - Return the location of final right parenthesis. - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ConvertVectorExprClass; - } - - // Iterators - child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } -}; - -/// ChooseExpr - GNU builtin-in function __builtin_choose_expr. -/// This AST node is similar to the conditional operator (?:) in C, with -/// the following exceptions: -/// - the test expression must be a integer constant expression. -/// - the expression returned acts like the chosen subexpression in every -/// visible way: the type is the same as that of the chosen subexpression, -/// and all predicates (whether it's an l-value, whether it's an integer -/// constant expression, etc.) return the same result as for the chosen -/// sub-expression. -class ChooseExpr : public Expr { - enum { COND, LHS, RHS, END_EXPR }; - Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. - SourceLocation BuiltinLoc, RParenLoc; - bool CondIsTrue; -public: - ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, - QualType t, ExprValueKind VK, ExprObjectKind OK, - SourceLocation RP, bool condIsTrue, - bool TypeDependent, bool ValueDependent) - : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, - (cond->isInstantiationDependent() || - lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (cond->containsUnexpandedParameterPack() || - lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) { - SubExprs[COND] = cond; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } - - /// \brief Build an empty __builtin_choose_expr. - explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } - - /// isConditionTrue - Return whether the condition is true (i.e. not - /// equal to zero). - bool isConditionTrue() const { - assert(!isConditionDependent() && - "Dependent condition isn't true or false"); - return CondIsTrue; - } - void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; } - - bool isConditionDependent() const { - return getCond()->isTypeDependent() || getCond()->isValueDependent(); - } - - /// getChosenSubExpr - Return the subexpression chosen according to the - /// condition. - Expr *getChosenSubExpr() const { - return isConditionTrue() ? getLHS() : getRHS(); - } - - Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } - void setCond(Expr *E) { SubExprs[COND] = E; } - Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } - void setLHS(Expr *E) { SubExprs[LHS] = E; } - Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - void setRHS(Expr *E) { SubExprs[RHS] = E; } - - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ChooseExprClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } -}; - -/// GNUNullExpr - Implements the GNU __null extension, which is a name -/// for a null pointer constant that has integral type (e.g., int or -/// long) and is the same size and alignment as a pointer. The __null -/// extension is typically only used by system headers, which define -/// NULL as __null in C++ rather than using 0 (which is an integer -/// that may not match the size of a pointer). -class GNUNullExpr : public Expr { - /// TokenLoc - The location of the __null keyword. - SourceLocation TokenLoc; - -public: - GNUNullExpr(QualType Ty, SourceLocation Loc) - : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false, - false), - TokenLoc(Loc) { } - - /// \brief Build an empty GNU __null expression. - explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } - - /// getTokenLocation - The location of the __null token. - SourceLocation getTokenLocation() const { return TokenLoc; } - void setTokenLocation(SourceLocation L) { TokenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == GNUNullExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// Represents a call to the builtin function \c __builtin_va_arg. -class VAArgExpr : public Expr { - Stmt *Val; - llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo; - SourceLocation BuiltinLoc, RParenLoc; -public: - VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo, - SourceLocation RPLoc, QualType t, bool IsMS) - : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(), - false, (TInfo->getType()->isInstantiationDependentType() || - e->isInstantiationDependent()), - (TInfo->getType()->containsUnexpandedParameterPack() || - e->containsUnexpandedParameterPack())), - Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {} - - /// Create an empty __builtin_va_arg expression. - explicit VAArgExpr(EmptyShell Empty) - : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {} - - const Expr *getSubExpr() const { return cast<Expr>(Val); } - Expr *getSubExpr() { return cast<Expr>(Val); } - void setSubExpr(Expr *E) { Val = E; } - - /// Returns whether this is really a Win64 ABI va_arg expression. - bool isMicrosoftABI() const { return TInfo.getInt(); } - void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); } - - TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); } - void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); } - - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == VAArgExprClass; - } - - // Iterators - child_range children() { return child_range(&Val, &Val+1); } -}; - -/// @brief Describes an C or C++ initializer list. -/// -/// InitListExpr describes an initializer list, which can be used to -/// initialize objects of different types, including -/// struct/class/union types, arrays, and vectors. For example: -/// -/// @code -/// struct foo x = { 1, { 2, 3 } }; -/// @endcode -/// -/// Prior to semantic analysis, an initializer list will represent the -/// initializer list as written by the user, but will have the -/// placeholder type "void". This initializer list is called the -/// syntactic form of the initializer, and may contain C99 designated -/// initializers (represented as DesignatedInitExprs), initializations -/// of subobject members without explicit braces, and so on. Clients -/// interested in the original syntax of the initializer list should -/// use the syntactic form of the initializer list. -/// -/// After semantic analysis, the initializer list will represent the -/// semantic form of the initializer, where the initializations of all -/// subobjects are made explicit with nested InitListExpr nodes and -/// C99 designators have been eliminated by placing the designated -/// initializations into the subobject they initialize. Additionally, -/// any "holes" in the initialization, where no initializer has been -/// specified for a particular subobject, will be replaced with -/// implicitly-generated ImplicitValueInitExpr expressions that -/// value-initialize the subobjects. Note, however, that the -/// initializer lists may still have fewer initializers than there are -/// elements to initialize within the object. -/// -/// After semantic analysis has completed, given an initializer list, -/// method isSemanticForm() returns true if and only if this is the -/// semantic form of the initializer list (note: the same AST node -/// may at the same time be the syntactic form). -/// Given the semantic form of the initializer list, one can retrieve -/// the syntactic form of that initializer list (when different) -/// using method getSyntacticForm(); the method returns null if applied -/// to a initializer list which is already in syntactic form. -/// Similarly, given the syntactic form (i.e., an initializer list such -/// that isSemanticForm() returns false), one can retrieve the semantic -/// form using method getSemanticForm(). -/// Since many initializer lists have the same syntactic and semantic forms, -/// getSyntacticForm() may return NULL, indicating that the current -/// semantic initializer list also serves as its syntactic form. -class InitListExpr : public Expr { - // FIXME: Eliminate this vector in favor of ASTContext allocation - typedef ASTVector<Stmt *> InitExprsTy; - InitExprsTy InitExprs; - SourceLocation LBraceLoc, RBraceLoc; - - /// The alternative form of the initializer list (if it exists). - /// The int part of the pair stores whether this initializer list is - /// in semantic form. If not null, the pointer points to: - /// - the syntactic form, if this is in semantic form; - /// - the semantic form, if this is in syntactic form. - llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm; - - /// \brief Either: - /// If this initializer list initializes an array with more elements than - /// there are initializers in the list, specifies an expression to be used - /// for value initialization of the rest of the elements. - /// Or - /// If this initializer list initializes a union, specifies which - /// field within the union will be initialized. - llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; - -public: - InitListExpr(const ASTContext &C, SourceLocation lbraceloc, - ArrayRef<Expr*> initExprs, SourceLocation rbraceloc); - - /// \brief Build an empty initializer list. - explicit InitListExpr(EmptyShell Empty) - : Expr(InitListExprClass, Empty) { } - - unsigned getNumInits() const { return InitExprs.size(); } - - /// \brief Retrieve the set of initializers. - Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } - - ArrayRef<Expr *> inits() { - return llvm::makeArrayRef(getInits(), getNumInits()); - } - - 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) { - assert(Init < getNumInits() && "Initializer access out of range!"); - return cast_or_null<Expr>(InitExprs[Init]); - } - - void setInit(unsigned Init, Expr *expr) { - assert(Init < getNumInits() && "Initializer access out of range!"); - InitExprs[Init] = expr; - - if (expr) { - ExprBits.TypeDependent |= expr->isTypeDependent(); - ExprBits.ValueDependent |= expr->isValueDependent(); - ExprBits.InstantiationDependent |= expr->isInstantiationDependent(); - ExprBits.ContainsUnexpandedParameterPack |= - expr->containsUnexpandedParameterPack(); - } - } - - /// \brief Reserve space for some number of initializers. - void reserveInits(const ASTContext &C, unsigned NumInits); - - /// @brief Specify the number of initializers - /// - /// If there are more than @p NumInits initializers, the remaining - /// initializers will be destroyed. If there are fewer than @p - /// NumInits initializers, NULL expressions will be added for the - /// unknown initializers. - void resizeInits(const ASTContext &Context, unsigned NumInits); - - /// @brief Updates the initializer at index @p Init with the new - /// expression @p expr, and returns the old expression at that - /// location. - /// - /// When @p Init is out of range for this initializer list, the - /// initializer list will be extended with NULL expressions to - /// accommodate the new entry. - Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr); - - /// \brief If this initializer list initializes an array with more elements - /// than there are initializers in the list, specifies an expression to be - /// used for value initialization of the rest of the elements. - Expr *getArrayFiller() { - return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); - } - const Expr *getArrayFiller() const { - return const_cast<InitListExpr *>(this)->getArrayFiller(); - } - void setArrayFiller(Expr *filler); - - /// \brief Return true if this is an array initializer and its array "filler" - /// has been set. - bool hasArrayFiller() const { return getArrayFiller(); } - - /// \brief If this initializes a union, specifies which field in the - /// union to initialize. - /// - /// Typically, this field is the first named field within the - /// union. However, a designated initializer can specify the - /// initialization of a different field within the union. - FieldDecl *getInitializedFieldInUnion() { - return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); - } - const FieldDecl *getInitializedFieldInUnion() const { - return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion(); - } - void setInitializedFieldInUnion(FieldDecl *FD) { - assert((FD == nullptr - || getInitializedFieldInUnion() == nullptr - || getInitializedFieldInUnion() == FD) - && "Only one field of a union may be initialized at a time!"); - ArrayFillerOrUnionFieldInit = FD; - } - - // Explicit InitListExpr's originate from source code (and have valid source - // locations). Implicit InitListExpr's are created by the semantic analyzer. - bool isExplicit() { - return LBraceLoc.isValid() && RBraceLoc.isValid(); - } - - // Is this an initializer for an array of characters, initialized by a string - // literal or an @encode? - bool isStringLiteralInit() const; - - SourceLocation getLBraceLoc() const { return LBraceLoc; } - void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } - SourceLocation getRBraceLoc() const { return RBraceLoc; } - void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; } - - bool isSemanticForm() const { return AltForm.getInt(); } - InitListExpr *getSemanticForm() const { - return isSemanticForm() ? nullptr : AltForm.getPointer(); - } - InitListExpr *getSyntacticForm() const { - return isSemanticForm() ? AltForm.getPointer() : nullptr; - } - - void setSyntacticForm(InitListExpr *Init) { - AltForm.setPointer(Init); - AltForm.setInt(true); - Init->AltForm.setPointer(this); - Init->AltForm.setInt(false); - } - - bool hadArrayRangeDesignator() const { - return InitListExprBits.HadArrayRangeDesignator != 0; - } - void sawArrayRangeDesignator(bool ARD = true) { - InitListExprBits.HadArrayRangeDesignator = ARD; - } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == InitListExprClass; - } - - // Iterators - child_range children() { - // FIXME: This does not include the array filler expression. - if (InitExprs.empty()) - return child_range(child_iterator(), child_iterator()); - return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); - } - - typedef InitExprsTy::iterator iterator; - typedef InitExprsTy::const_iterator const_iterator; - typedef InitExprsTy::reverse_iterator reverse_iterator; - typedef InitExprsTy::const_reverse_iterator const_reverse_iterator; - - iterator begin() { return InitExprs.begin(); } - const_iterator begin() const { return InitExprs.begin(); } - iterator end() { return InitExprs.end(); } - const_iterator end() const { return InitExprs.end(); } - reverse_iterator rbegin() { return InitExprs.rbegin(); } - const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } - reverse_iterator rend() { return InitExprs.rend(); } - const_reverse_iterator rend() const { return InitExprs.rend(); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// @brief Represents a C99 designated initializer expression. -/// -/// A designated initializer expression (C99 6.7.8) contains one or -/// more designators (which can be field designators, array -/// designators, or GNU array-range designators) followed by an -/// expression that initializes the field or element(s) that the -/// designators refer to. For example, given: -/// -/// @code -/// struct point { -/// double x; -/// double y; -/// }; -/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; -/// @endcode -/// -/// The InitListExpr contains three DesignatedInitExprs, the first of -/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two -/// designators, one array designator for @c [2] followed by one field -/// designator for @c .y. The initialization expression will be 1.0. -class DesignatedInitExpr final - : public Expr, - private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> { -public: - /// \brief Forward declaration of the Designator class. - class Designator; - -private: - /// The location of the '=' or ':' prior to the actual initializer - /// expression. - SourceLocation EqualOrColonLoc; - - /// Whether this designated initializer used the GNU deprecated - /// syntax rather than the C99 '=' syntax. - bool GNUSyntax : 1; - - /// The number of designators in this initializer expression. - unsigned NumDesignators : 15; - - /// The number of subexpressions of this initializer expression, - /// which contains both the initializer and any additional - /// expressions used by array and array-range designators. - unsigned NumSubExprs : 16; - - /// \brief The designators in this designated initialization - /// expression. - Designator *Designators; - - - DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators, - const Designator *Designators, - SourceLocation EqualOrColonLoc, bool GNUSyntax, - ArrayRef<Expr*> IndexExprs, Expr *Init); - - explicit DesignatedInitExpr(unsigned NumSubExprs) - : Expr(DesignatedInitExprClass, EmptyShell()), - NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { } - -public: - /// A field designator, e.g., ".x". - struct FieldDesignator { - /// Refers to the field that is being initialized. The low bit - /// of this field determines whether this is actually a pointer - /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When - /// initially constructed, a field designator will store an - /// IdentifierInfo*. After semantic analysis has resolved that - /// name, the field designator will instead store a FieldDecl*. - uintptr_t NameOrField; - - /// The location of the '.' in the designated initializer. - unsigned DotLoc; - - /// The location of the field name in the designated initializer. - unsigned FieldLoc; - }; - - /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator { - /// Location of the first index expression within the designated - /// initializer expression's list of subexpressions. - unsigned Index; - /// The location of the '[' starting the array range designator. - unsigned LBracketLoc; - /// The location of the ellipsis separating the start and end - /// indices. Only valid for GNU array-range designators. - unsigned EllipsisLoc; - /// The location of the ']' terminating the array range designator. - unsigned RBracketLoc; - }; - - /// @brief Represents a single C99 designator. - /// - /// @todo This class is infuriatingly similar to clang::Designator, - /// but minor differences (storing indices vs. storing pointers) - /// keep us from reusing it. Try harder, later, to rectify these - /// differences. - class Designator { - /// @brief The kind of designator this describes. - enum { - FieldDesignator, - ArrayDesignator, - ArrayRangeDesignator - } Kind; - - union { - /// A field designator, e.g., ".x". - struct FieldDesignator Field; - /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator ArrayOrRange; - }; - friend class DesignatedInitExpr; - - public: - Designator() {} - - /// @brief Initializes a field designator. - Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, - SourceLocation FieldLoc) - : Kind(FieldDesignator) { - Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; - Field.DotLoc = DotLoc.getRawEncoding(); - Field.FieldLoc = FieldLoc.getRawEncoding(); - } - - /// @brief Initializes an array designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation RBracketLoc) - : Kind(ArrayDesignator) { - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); - ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding(); - ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); - } - - /// @brief Initializes a GNU array-range designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation EllipsisLoc, SourceLocation RBracketLoc) - : Kind(ArrayRangeDesignator) { - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); - ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding(); - ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); - } - - bool isFieldDesignator() const { return Kind == FieldDesignator; } - bool isArrayDesignator() const { return Kind == ArrayDesignator; } - bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } - - IdentifierInfo *getFieldName() const; - - FieldDecl *getField() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - if (Field.NameOrField & 0x01) - return nullptr; - else - return reinterpret_cast<FieldDecl *>(Field.NameOrField); - } - - void setField(FieldDecl *FD) { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - Field.NameOrField = reinterpret_cast<uintptr_t>(FD); - } - - SourceLocation getDotLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return SourceLocation::getFromRawEncoding(Field.DotLoc); - } - - SourceLocation getFieldLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return SourceLocation::getFromRawEncoding(Field.FieldLoc); - } - - SourceLocation getLBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && - "Only valid on an array or array-range designator"); - return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc); - } - - SourceLocation getRBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && - "Only valid on an array or array-range designator"); - return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc); - } - - SourceLocation getEllipsisLoc() const { - assert(Kind == ArrayRangeDesignator && - "Only valid on an array-range designator"); - return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc); - } - - unsigned getFirstExprIndex() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && - "Only valid on an array or array-range designator"); - return ArrayOrRange.Index; - } - - SourceLocation getLocStart() const LLVM_READONLY { - if (Kind == FieldDesignator) - return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); - else - return getLBracketLoc(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); - } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocStart(), getLocEnd()); - } - }; - - static DesignatedInitExpr *Create(const ASTContext &C, - Designator *Designators, - unsigned NumDesignators, - ArrayRef<Expr*> IndexExprs, - SourceLocation EqualOrColonLoc, - bool GNUSyntax, Expr *Init); - - static DesignatedInitExpr *CreateEmpty(const ASTContext &C, - unsigned NumIndexExprs); - - /// @brief Returns the number of designators in this initializer. - unsigned size() const { return NumDesignators; } - - // Iterator access to the designators. - typedef Designator *designators_iterator; - designators_iterator designators_begin() { return Designators; } - designators_iterator designators_end() { - return Designators + NumDesignators; - } - - typedef const Designator *const_designators_iterator; - const_designators_iterator designators_begin() const { return Designators; } - const_designators_iterator designators_end() const { - return Designators + NumDesignators; - } - - typedef llvm::iterator_range<designators_iterator> designators_range; - designators_range designators() { - return designators_range(designators_begin(), designators_end()); - } - - typedef llvm::iterator_range<const_designators_iterator> - designators_const_range; - designators_const_range designators() const { - return designators_const_range(designators_begin(), designators_end()); - } - - 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()); - } - - typedef std::reverse_iterator<const_designators_iterator> - const_reverse_designators_iterator; - const_reverse_designators_iterator designators_rbegin() const { - return const_reverse_designators_iterator(designators_end()); - } - const_reverse_designators_iterator designators_rend() const { - return const_reverse_designators_iterator(designators_begin()); - } - - Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } - - void setDesignators(const ASTContext &C, const Designator *Desigs, - unsigned NumDesigs); - - Expr *getArrayIndex(const Designator &D) const; - Expr *getArrayRangeStart(const Designator &D) const; - Expr *getArrayRangeEnd(const Designator &D) const; - - /// @brief Retrieve the location of the '=' that precedes the - /// initializer value itself, if present. - SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } - void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } - - /// @brief Determines whether this designated initializer used the - /// deprecated GNU syntax for designated initializers. - bool usesGNUSyntax() const { return GNUSyntax; } - void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } - - /// @brief Retrieve the initializer value. - Expr *getInit() const { - return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); - } - - void setInit(Expr *init) { - *child_begin() = init; - } - - /// \brief Retrieve the total number of subexpressions in this - /// designated initializer expression, including the actual - /// initialized value and any expressions that occur within array - /// and array-range designators. - unsigned getNumSubExprs() const { return NumSubExprs; } - - Expr *getSubExpr(unsigned Idx) const { - assert(Idx < NumSubExprs && "Subscript out of range"); - return cast<Expr>(getTrailingObjects<Stmt *>()[Idx]); - } - - void setSubExpr(unsigned Idx, Expr *E) { - assert(Idx < NumSubExprs && "Subscript out of range"); - getTrailingObjects<Stmt *>()[Idx] = E; - } - - /// \brief Replaces the designator at index @p Idx with the series - /// of designators in [First, Last). - void ExpandDesignator(const ASTContext &C, unsigned Idx, - const Designator *First, const Designator *Last); - - SourceRange getDesignatorsSourceRange() const; - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DesignatedInitExprClass; - } - - // Iterators - child_range children() { - Stmt **begin = getTrailingObjects<Stmt *>(); - return child_range(begin, begin + NumSubExprs); - } - - friend TrailingObjects; -}; - -/// \brief Represents a place-holder for an object not to be initialized by -/// anything. -/// -/// This only makes sense when it appears as part of an updater of a -/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE -/// initializes a big object, and the NoInitExpr's mark the spots within the -/// big object not to be overwritten by the updater. -/// -/// \see DesignatedInitUpdateExpr -class NoInitExpr : public Expr { -public: - explicit NoInitExpr(QualType ty) - : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary, - false, false, ty->isInstantiationDependentType(), false) { } - - explicit NoInitExpr(EmptyShell Empty) - : Expr(NoInitExprClass, Empty) { } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == NoInitExprClass; - } - - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -// In cases like: -// struct Q { int a, b, c; }; -// Q *getQ(); -// void foo() { -// struct A { Q q; } a = { *getQ(), .q.b = 3 }; -// } -// -// We will have an InitListExpr for a, with type A, and then a -// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE -// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3" -// -class DesignatedInitUpdateExpr : public Expr { - // BaseAndUpdaterExprs[0] is the base expression; - // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base. - Stmt *BaseAndUpdaterExprs[2]; - -public: - DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc, - Expr *baseExprs, SourceLocation rBraceLoc); - - explicit DesignatedInitUpdateExpr(EmptyShell Empty) - : Expr(DesignatedInitUpdateExprClass, Empty) { } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DesignatedInitUpdateExprClass; - } - - Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); } - void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; } - - InitListExpr *getUpdater() const { - return cast<InitListExpr>(BaseAndUpdaterExprs[1]); - } - void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; } - - // Iterators - // children = the base and the updater - child_range children() { - return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2); - } -}; - -/// \brief Represents an implicitly-generated value initialization of -/// an object of a given type. -/// -/// Implicit value initializations occur within semantic initializer -/// list expressions (InitListExpr) as placeholders for subobject -/// initializations not explicitly specified by the user. -/// -/// \see InitListExpr -class ImplicitValueInitExpr : public Expr { -public: - explicit ImplicitValueInitExpr(QualType ty) - : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, - false, false, ty->isInstantiationDependentType(), false) { } - - /// \brief Construct an empty implicit value initialization. - explicit ImplicitValueInitExpr(EmptyShell Empty) - : Expr(ImplicitValueInitExprClass, Empty) { } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ImplicitValueInitExprClass; - } - - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -class ParenListExpr : public Expr { - Stmt **Exprs; - unsigned NumExprs; - SourceLocation LParenLoc, RParenLoc; - -public: - ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef<Expr*> exprs, SourceLocation rparenloc); - - /// \brief Build an empty paren list. - explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } - - unsigned getNumExprs() const { return NumExprs; } - - const Expr* getExpr(unsigned Init) const { - assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null<Expr>(Exprs[Init]); - } - - Expr* getExpr(unsigned Init) { - assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null<Expr>(Exprs[Init]); - } - - Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } - - ArrayRef<Expr *> exprs() { - return llvm::makeArrayRef(getExprs(), getNumExprs()); - } - - SourceLocation getLParenLoc() const { return LParenLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ParenListExprClass; - } - - // Iterators - child_range children() { - return child_range(&Exprs[0], &Exprs[0]+NumExprs); - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief Represents a C11 generic selection. -/// -/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling -/// expression, followed by one or more generic associations. Each generic -/// association specifies a type name and an expression, or "default" and an -/// expression (in which case it is known as a default generic association). -/// The type and value of the generic selection are identical to those of its -/// result expression, which is defined as the expression in the generic -/// association with a type name that is compatible with the type of the -/// controlling expression, or the expression in the default generic association -/// if no types are compatible. For example: -/// -/// @code -/// _Generic(X, double: 1, float: 2, default: 3) -/// @endcode -/// -/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f -/// or 3 if "hello". -/// -/// As an extension, generic selections are allowed in C++, where the following -/// additional semantics apply: -/// -/// Any generic selection whose controlling expression is type-dependent or -/// which names a dependent type in its association list is result-dependent, -/// which means that the choice of result expression is dependent. -/// Result-dependent generic associations are both type- and value-dependent. -class GenericSelectionExpr : public Expr { - enum { CONTROLLING, END_EXPR }; - TypeSourceInfo **AssocTypes; - Stmt **SubExprs; - unsigned NumAssocs, ResultIndex; - SourceLocation GenericLoc, DefaultLoc, RParenLoc; - -public: - GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef<TypeSourceInfo*> AssocTypes, - ArrayRef<Expr*> AssocExprs, - SourceLocation DefaultLoc, SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack, - unsigned ResultIndex); - - /// This constructor is used in the result-dependent case. - GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef<TypeSourceInfo*> AssocTypes, - ArrayRef<Expr*> AssocExprs, - SourceLocation DefaultLoc, SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack); - - explicit GenericSelectionExpr(EmptyShell Empty) - : Expr(GenericSelectionExprClass, Empty) { } - - unsigned getNumAssocs() const { return NumAssocs; } - - SourceLocation getGenericLoc() const { return GenericLoc; } - SourceLocation getDefaultLoc() const { return DefaultLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - const Expr *getAssocExpr(unsigned i) const { - return cast<Expr>(SubExprs[END_EXPR+i]); - } - Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); } - - const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { - return AssocTypes[i]; - } - TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } - - QualType getAssocType(unsigned i) const { - if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) - return TS->getType(); - else - return QualType(); - } - - const Expr *getControllingExpr() const { - return cast<Expr>(SubExprs[CONTROLLING]); - } - Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); } - - /// Whether this generic selection is result-dependent. - bool isResultDependent() const { return ResultIndex == -1U; } - - /// The zero-based index of the result expression's generic association in - /// the generic selection's association list. Defined only if the - /// generic selection is not result-dependent. - unsigned getResultIndex() const { - assert(!isResultDependent() && "Generic selection is result-dependent"); - return ResultIndex; - } - - /// The generic selection's result expression. Defined only if the - /// generic selection is not result-dependent. - const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } - Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } - - SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == GenericSelectionExprClass; - } - - child_range children() { - return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); - } - - friend class ASTStmtReader; -}; - -//===----------------------------------------------------------------------===// -// Clang Extensions -//===----------------------------------------------------------------------===// - -/// ExtVectorElementExpr - This represents access to specific elements of a -/// vector, and may occur on the left hand side or right hand side. For example -/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. -/// -/// Note that the base may have either vector or pointer to vector type, just -/// like a struct field reference. -/// -class ExtVectorElementExpr : public Expr { - Stmt *Base; - IdentifierInfo *Accessor; - SourceLocation AccessorLoc; -public: - 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->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), Accessor(&accessor), AccessorLoc(loc) {} - - /// \brief Build an empty vector element expression. - explicit ExtVectorElementExpr(EmptyShell Empty) - : Expr(ExtVectorElementExprClass, Empty) { } - - const Expr *getBase() const { return cast<Expr>(Base); } - Expr *getBase() { return cast<Expr>(Base); } - void setBase(Expr *E) { Base = E; } - - IdentifierInfo &getAccessor() const { return *Accessor; } - void setAccessor(IdentifierInfo *II) { Accessor = II; } - - SourceLocation getAccessorLoc() const { return AccessorLoc; } - void setAccessorLoc(SourceLocation L) { AccessorLoc = L; } - - /// getNumElements - Get the number of components being selected. - unsigned getNumElements() const; - - /// containsDuplicateElements - Return true if any element access is - /// repeated. - bool containsDuplicateElements() const; - - /// getEncodedElementAccess - Encode the elements accessed into an llvm - /// aggregate Constant of ConstantInt(s). - void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const; - - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return AccessorLoc; } - - /// isArrow - Return true if the base expression is a pointer to vector, - /// return false if the base expression is a vector. - bool isArrow() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ExtVectorElementExprClass; - } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } -}; - -/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. -/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } -class BlockExpr : public Expr { -protected: - BlockDecl *TheBlock; -public: - BlockExpr(BlockDecl *BD, QualType ty) - : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), ty->isDependentType(), - ty->isInstantiationDependentType() || BD->isDependentContext(), - false), - TheBlock(BD) {} - - /// \brief Build an empty block expression. - explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } - - const BlockDecl *getBlockDecl() const { return TheBlock; } - BlockDecl *getBlockDecl() { return TheBlock; } - void setBlockDecl(BlockDecl *BD) { TheBlock = BD; } - - // Convenience functions for probing the underlying BlockDecl. - SourceLocation getCaretLocation() const; - const Stmt *getBody() const; - Stmt *getBody(); - - SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); } - - /// getFunctionType - Return the underlying function type for this block. - const FunctionProtoType *getFunctionType() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BlockExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] -/// This AST node provides support for reinterpreting a type to another -/// type of the same size. -class AsTypeExpr : public Expr { -private: - Stmt *SrcExpr; - SourceLocation BuiltinLoc, RParenLoc; - - friend class ASTReader; - friend class ASTStmtReader; - explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} - -public: - AsTypeExpr(Expr* SrcExpr, QualType DstType, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(AsTypeExprClass, DstType, VK, OK, - DstType->isDependentType(), - DstType->isDependentType() || SrcExpr->isValueDependent(), - (DstType->isInstantiationDependentType() || - SrcExpr->isInstantiationDependent()), - (DstType->containsUnexpandedParameterPack() || - SrcExpr->containsUnexpandedParameterPack())), - SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} - - /// getSrcExpr - Return the Expr to be converted. - Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } - - /// getBuiltinLoc - Return the location of the __builtin_astype token. - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - - /// getRParenLoc - Return the location of final right parenthesis. - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == AsTypeExprClass; - } - - // Iterators - child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } -}; - -/// PseudoObjectExpr - An expression which accesses a pseudo-object -/// l-value. A pseudo-object is an abstract object, accesses to which -/// are translated to calls. The pseudo-object expression has a -/// syntactic form, which shows how the expression was actually -/// written in the source code, and a semantic form, which is a series -/// of expressions to be executed in order which detail how the -/// operation is actually evaluated. Optionally, one of the semantic -/// forms may also provide a result value for the expression. -/// -/// If any of the semantic-form expressions is an OpaqueValueExpr, -/// that OVE is required to have a source expression, and it is bound -/// to the result of that source expression. Such OVEs may appear -/// only in subsequent semantic-form expressions and as -/// sub-expressions of the syntactic form. -/// -/// PseudoObjectExpr should be used only when an operation can be -/// usefully described in terms of fairly simple rewrite rules on -/// objects and functions that are meant to be used by end-developers. -/// For example, under the Itanium ABI, dynamic casts are implemented -/// as a call to a runtime function called __dynamic_cast; using this -/// class to describe that would be inappropriate because that call is -/// not really part of the user-visible semantics, and instead the -/// cast is properly reflected in the AST and IR-generation has been -/// taught to generate the call as necessary. In contrast, an -/// Objective-C property access is semantically defined to be -/// equivalent to a particular message send, and this is very much -/// part of the user model. The name of this class encourages this -/// modelling design. -class PseudoObjectExpr final - : public Expr, - private llvm::TrailingObjects<PseudoObjectExpr, Expr *> { - // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions. - // Always at least two, because the first sub-expression is the - // syntactic form. - - // PseudoObjectExprBits.ResultIndex - The index of the - // sub-expression holding the result. 0 means the result is void, - // which is unambiguous because it's the index of the syntactic - // form. Note that this is therefore 1 higher than the value passed - // in to Create, which is an index within the semantic forms. - // Note also that ASTStmtWriter assumes this encoding. - - Expr **getSubExprsBuffer() { return getTrailingObjects<Expr *>(); } - const Expr * const *getSubExprsBuffer() const { - return getTrailingObjects<Expr *>(); - } - - PseudoObjectExpr(QualType type, ExprValueKind VK, - Expr *syntactic, ArrayRef<Expr*> semantic, - unsigned resultIndex); - - PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs); - - unsigned getNumSubExprs() const { - return PseudoObjectExprBits.NumSubExprs; - } - -public: - /// NoResult - A value for the result index indicating that there is - /// no semantic result. - enum : unsigned { NoResult = ~0U }; - - static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic, - ArrayRef<Expr*> semantic, - unsigned resultIndex); - - static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell, - unsigned numSemanticExprs); - - /// Return the syntactic form of this expression, i.e. the - /// expression it actually looks like. Likely to be expressed in - /// terms of OpaqueValueExprs bound in the semantic form. - Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; } - const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; } - - /// Return the index of the result-bearing expression into the semantics - /// expressions, or PseudoObjectExpr::NoResult if there is none. - unsigned getResultExprIndex() const { - if (PseudoObjectExprBits.ResultIndex == 0) return NoResult; - return PseudoObjectExprBits.ResultIndex - 1; - } - - /// Return the result-bearing expression, or null if there is none. - Expr *getResultExpr() { - if (PseudoObjectExprBits.ResultIndex == 0) - return nullptr; - return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex]; - } - const Expr *getResultExpr() const { - return const_cast<PseudoObjectExpr*>(this)->getResultExpr(); - } - - unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; } - - typedef Expr * const *semantics_iterator; - typedef const Expr * const *const_semantics_iterator; - semantics_iterator semantics_begin() { - return getSubExprsBuffer() + 1; - } - const_semantics_iterator semantics_begin() const { - return getSubExprsBuffer() + 1; - } - semantics_iterator semantics_end() { - return getSubExprsBuffer() + getNumSubExprs(); - } - const_semantics_iterator semantics_end() const { - return getSubExprsBuffer() + getNumSubExprs(); - } - - llvm::iterator_range<semantics_iterator> semantics() { - return llvm::make_range(semantics_begin(), semantics_end()); - } - llvm::iterator_range<const_semantics_iterator> semantics() const { - return llvm::make_range(semantics_begin(), semantics_end()); - } - - Expr *getSemanticExpr(unsigned index) { - assert(index + 1 < getNumSubExprs()); - return getSubExprsBuffer()[index + 1]; - } - const Expr *getSemanticExpr(unsigned index) const { - return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index); - } - - SourceLocation getExprLoc() const LLVM_READONLY { - return getSyntacticForm()->getExprLoc(); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getSyntacticForm()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSyntacticForm()->getLocEnd(); - } - - child_range children() { - Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer()); - return child_range(cs, cs + getNumSubExprs()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PseudoObjectExprClass; - } - - friend TrailingObjects; - friend class ASTStmtReader; -}; - -/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, -/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the -/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>. -/// All of these instructions take one primary pointer and at least one memory -/// order. -class AtomicExpr : public Expr { -public: - enum AtomicOp { -#define BUILTIN(ID, TYPE, ATTRS) -#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, -#include "clang/Basic/Builtins.def" - // Avoid trailing comma - BI_First = 0 - }; - - // The ABI values for various atomic memory orderings. - enum AtomicOrderingKind { - AO_ABI_memory_order_relaxed = 0, - AO_ABI_memory_order_consume = 1, - AO_ABI_memory_order_acquire = 2, - AO_ABI_memory_order_release = 3, - AO_ABI_memory_order_acq_rel = 4, - AO_ABI_memory_order_seq_cst = 5 - }; - -private: - enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; - Stmt* SubExprs[END_EXPR]; - unsigned NumSubExprs; - SourceLocation BuiltinLoc, RParenLoc; - AtomicOp Op; - - friend class ASTStmtReader; - -public: - AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, - AtomicOp op, SourceLocation RP); - - /// \brief Determine the number of arguments the specified atomic builtin - /// should have. - static unsigned getNumSubExprs(AtomicOp Op); - - /// \brief Build an empty AtomicExpr. - explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } - - Expr *getPtr() const { - return cast<Expr>(SubExprs[PTR]); - } - Expr *getOrder() const { - return cast<Expr>(SubExprs[ORDER]); - } - Expr *getVal1() const { - if (Op == AO__c11_atomic_init) - return cast<Expr>(SubExprs[ORDER]); - assert(NumSubExprs > VAL1); - return cast<Expr>(SubExprs[VAL1]); - } - Expr *getOrderFail() const { - assert(NumSubExprs > ORDER_FAIL); - return cast<Expr>(SubExprs[ORDER_FAIL]); - } - Expr *getVal2() const { - if (Op == AO__atomic_exchange) - return cast<Expr>(SubExprs[ORDER_FAIL]); - assert(NumSubExprs > VAL2); - return cast<Expr>(SubExprs[VAL2]); - } - Expr *getWeak() const { - assert(NumSubExprs > WEAK); - return cast<Expr>(SubExprs[WEAK]); - } - - AtomicOp getOp() const { return Op; } - unsigned getNumSubExprs() { return NumSubExprs; } - - Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } - - bool isVolatile() const { - return getPtr()->getType()->getPointeeType().isVolatileQualified(); - } - - bool isCmpXChg() const { - return getOp() == AO__c11_atomic_compare_exchange_strong || - getOp() == AO__c11_atomic_compare_exchange_weak || - getOp() == AO__atomic_compare_exchange || - getOp() == AO__atomic_compare_exchange_n; - } - - SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == AtomicExprClass; - } - - // Iterators - child_range children() { - return child_range(SubExprs, SubExprs+NumSubExprs); - } -}; - -/// TypoExpr - Internal placeholder for expressions where typo correction -/// still needs to be performed and/or an error diagnostic emitted. -class TypoExpr : public Expr { -public: - TypoExpr(QualType T) - : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary, - /*isTypeDependent*/ true, - /*isValueDependent*/ true, - /*isInstantiationDependent*/ true, - /*containsUnexpandedParameterPack*/ false) { - assert(T->isDependentType() && "TypoExpr given a non-dependent type"); - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == TypoExprClass; - } - -}; -} // end namespace clang - -#endif // LLVM_CLANG_AST_EXPR_H diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h deleted file mode 100644 index 0608aba..0000000 --- a/include/clang/AST/ExprCXX.h +++ /dev/null @@ -1,4179 +0,0 @@ -//===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the clang::Expr interface and subclasses for C++ expressions. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_EXPRCXX_H -#define LLVM_CLANG_AST_EXPRCXX_H - -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/LambdaCapture.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/UnresolvedSet.h" -#include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/TypeTraits.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -class CXXConstructorDecl; -class CXXDestructorDecl; -class CXXMethodDecl; -class CXXTemporary; -class MSPropertyDecl; -class TemplateArgumentListInfo; -class UuidAttr; - -//===--------------------------------------------------------------------===// -// C++ Expressions. -//===--------------------------------------------------------------------===// - -/// \brief A call to an overloaded operator written using operator -/// syntax. -/// -/// Represents a call to an overloaded operator written using operator -/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a -/// normal call, this AST node provides better information about the -/// syntactic representation of the call. -/// -/// In a C++ template, this expression node kind will be used whenever -/// any of the arguments are type-dependent. In this case, the -/// function itself will be a (possibly empty) set of functions and -/// function templates that were found by name lookup at template -/// definition time. -class CXXOperatorCallExpr : public CallExpr { - /// \brief The overloaded operator. - OverloadedOperatorKind Operator; - SourceRange Range; - - // Record the FP_CONTRACT state that applies to this operator call. Only - // meaningful for floating point types. For other types this value can be - // set to false. - unsigned FPContractable : 1; - - SourceRange getSourceRangeImpl() const LLVM_READONLY; -public: - CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, - ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation operatorloc, bool fpContractable) - : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK, - operatorloc), - Operator(Op), FPContractable(fpContractable) { - Range = getSourceRangeImpl(); - } - explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : - CallExpr(C, CXXOperatorCallExprClass, Empty) { } - - - /// \brief Returns the kind of overloaded operator that this - /// expression refers to. - OverloadedOperatorKind getOperator() const { return Operator; } - - /// \brief Returns the location of the operator symbol in the expression. - /// - /// When \c getOperator()==OO_Call, this is the location of the right - /// parentheses; when \c getOperator()==OO_Subscript, this is the location - /// of the right bracket. - SourceLocation getOperatorLoc() const { return getRParenLoc(); } - - SourceLocation getExprLoc() const LLVM_READONLY { - return (Operator < OO_Plus || Operator >= OO_Arrow || - Operator == OO_PlusPlus || Operator == OO_MinusMinus) - ? getLocStart() - : getOperatorLoc(); - } - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const { return Range; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXOperatorCallExprClass; - } - - // Set the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } - - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - bool isFPContractable() const { return FPContractable; } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// Represents a call to a member function that -/// may be written either with member call syntax (e.g., "obj.func()" -/// or "objptr->func()") or with normal function-call syntax -/// ("func()") within a member function that ends up calling a member -/// function. The callee in either case is a MemberExpr that contains -/// both the object argument and the member function, while the -/// arguments are the arguments within the parentheses (not including -/// the object argument). -class CXXMemberCallExpr : public CallExpr { -public: - CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args, - QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, t, VK, RP) {} - - CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CXXMemberCallExprClass, Empty) { } - - /// \brief Retrieves the implicit object argument for the member call. - /// - /// For example, in "x.f(5)", this returns the sub-expression "x". - Expr *getImplicitObjectArgument() const; - - /// \brief Retrieves the declaration of the called method. - CXXMethodDecl *getMethodDecl() const; - - /// \brief 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() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXMemberCallExprClass; - } -}; - -/// \brief 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, - ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation RP) - : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, 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; - } -}; - -/// \brief Abstract class common to all of the C++ "named"/"keyword" casts. -/// -/// This abstract class is inherited by all of the classes -/// representing "named" casts: CXXStaticCastExpr for \c static_cast, -/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for -/// reinterpret_cast, and CXXConstCastExpr for \c const_cast. -class CXXNamedCastExpr : public ExplicitCastExpr { -private: - SourceLocation Loc; // the location of the casting op - SourceLocation RParenLoc; // the location of the right parenthesis - SourceRange AngleBrackets; // range for '<' '>' - -protected: - CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, - CastKind kind, Expr *op, unsigned PathSize, - TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc, - SourceRange AngleBrackets) - : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), - RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} - - 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., - /// \c static_cast. - SourceLocation getOperatorLoc() const { return Loc; } - - /// \brief Retrieve the location of the closing parenthesis. - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } - - static bool classof(const Stmt *T) { - switch (T->getStmtClass()) { - case CXXStaticCastExprClass: - case CXXDynamicCastExprClass: - case CXXReinterpretCastExprClass: - case CXXConstCastExprClass: - return true; - default: - return false; - } - } -}; - -/// \brief A C++ \c static_cast expression (C++ [expr.static.cast]). -/// -/// This expression node represents a C++ static cast, e.g., -/// \c static_cast<int>(1.0). -class CXXStaticCastExpr final - : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { - CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, - unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation RParenLoc, - SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} - - explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) - : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } - -public: - static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind K, Expr *Op, - const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets); - static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXStaticCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). -/// -/// This expression node represents a dynamic cast, e.g., -/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time -/// check to determine how to perform the type conversion. -class CXXDynamicCastExpr final - : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { - CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, - Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation RParenLoc, - SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} - - explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } - -public: - static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind Kind, Expr *Op, - const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets); - - static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context, - unsigned pathSize); - - bool isAlwaysNull() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDynamicCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). -/// -/// This expression node represents a reinterpret cast, e.g., -/// @c reinterpret_cast<int>(VoidPtr). -/// -/// A reinterpret_cast provides a differently-typed view of a value but -/// (in Clang, as in most C++ implementations) performs no actual work at -/// run time. -class CXXReinterpretCastExpr final - : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXReinterpretCastExpr, - CXXBaseSpecifier *> { - CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, - Expr *op, unsigned pathSize, - TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc, - SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, - pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} - - CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } - -public: - static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind Kind, - Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets); - static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context, - unsigned pathSize); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXReinterpretCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). -/// -/// This expression node represents a const cast, e.g., -/// \c const_cast<char*>(PtrToConstChar). -/// -/// A const_cast can remove type qualifiers but does not change the underlying -/// value. -class CXXConstCastExpr final - : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { - CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, - 0, writtenTy, l, RParenLoc, AngleBrackets) {} - - explicit CXXConstCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } - -public: - static CXXConstCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, Expr *Op, - TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets); - static CXXConstCastExpr *CreateEmpty(const ASTContext &Context); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXConstCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// \brief A call to a literal operator (C++11 [over.literal]) -/// written as a user-defined literal (C++11 [lit.ext]). -/// -/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this -/// is semantically equivalent to a normal call, this AST node provides better -/// information about the syntactic representation of the literal. -/// -/// Since literal operators are never found by ADL and can only be declared at -/// namespace scope, a user-defined literal is never dependent. -class UserDefinedLiteral : public CallExpr { - /// \brief The location of a ud-suffix within the literal. - SourceLocation UDSuffixLoc; - -public: - UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args, - QualType T, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc) - : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, T, VK, LitEndLoc), - UDSuffixLoc(SuffixLoc) {} - explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) - : CallExpr(C, UserDefinedLiteralClass, Empty) {} - - /// The kind of literal operator which is invoked. - enum LiteralOperatorKind { - LOK_Raw, ///< Raw form: operator "" X (const char *) - LOK_Template, ///< Raw form: operator "" X<cs...> () - LOK_Integer, ///< operator "" X (unsigned long long) - LOK_Floating, ///< operator "" X (long double) - LOK_String, ///< operator "" X (const CharT *, size_t) - LOK_Character ///< operator "" X (CharT) - }; - - /// \brief Returns the kind of literal operator invocation - /// which this expression represents. - LiteralOperatorKind getLiteralOperatorKind() const; - - /// \brief If this is not a raw user-defined literal, get the - /// underlying cooked literal (representing the literal with the suffix - /// removed). - Expr *getCookedLiteral(); - const Expr *getCookedLiteral() const { - return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); - } - - SourceLocation getLocStart() const { - if (getLiteralOperatorKind() == LOK_Template) - return getRParenLoc(); - return getArg(0)->getLocStart(); - } - SourceLocation getLocEnd() const { return getRParenLoc(); } - - - /// \brief Returns the location of a ud-suffix in the expression. - /// - /// For a string literal, there may be multiple identical suffixes. This - /// returns the first. - SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } - - /// \brief Returns the ud-suffix specified for this literal. - const IdentifierInfo *getUDSuffix() const; - - static bool classof(const Stmt *S) { - return S->getStmtClass() == UserDefinedLiteralClass; - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals). -/// -class CXXBoolLiteralExpr : public Expr { - bool Value; - SourceLocation Loc; -public: - CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(val), Loc(l) {} - - explicit CXXBoolLiteralExpr(EmptyShell Empty) - : Expr(CXXBoolLiteralExprClass, Empty) { } - - bool getValue() const { return Value; } - void setValue(bool V) { Value = V; } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXBoolLiteralExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief The null pointer literal (C++11 [lex.nullptr]) -/// -/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. -class CXXNullPtrLiteralExpr : public Expr { - SourceLocation Loc; -public: - CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : - Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Loc(l) {} - - explicit CXXNullPtrLiteralExpr(EmptyShell Empty) - : Expr(CXXNullPtrLiteralExprClass, Empty) { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXNullPtrLiteralExprClass; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief Implicit construction of a std::initializer_list<T> object from an -/// array temporary within list-initialization (C++11 [dcl.init.list]p5). -class CXXStdInitializerListExpr : public Expr { - Stmt *SubExpr; - - CXXStdInitializerListExpr(EmptyShell Empty) - : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {} - -public: - CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) - : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, - Ty->isDependentType(), SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - SubExpr(SubExpr) {} - - Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } - const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } - - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExpr->getLocEnd(); - } - SourceRange getSourceRange() const LLVM_READONLY { - return SubExpr->getSourceRange(); - } - - static bool classof(const Stmt *S) { - return S->getStmtClass() == CXXStdInitializerListExprClass; - } - - child_range children() { return child_range(&SubExpr, &SubExpr + 1); } - - friend class ASTReader; - friend class ASTStmtReader; -}; - -/// A C++ \c typeid expression (C++ [expr.typeid]), which gets -/// the \c type_info that corresponds to the supplied type, or the (possibly -/// dynamic) type of the supplied expression. -/// -/// This represents code like \c typeid(int) or \c typeid(*objPtr) -class CXXTypeidExpr : public Expr { -private: - llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; - SourceRange Range; - -public: - CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : 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()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } - - CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) - : 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->isTypeDependent() || Operand->isValueDependent(), - Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } - - CXXTypeidExpr(EmptyShell Empty, bool isExpr) - : Expr(CXXTypeidExprClass, Empty) { - if (isExpr) - Operand = (Expr*)nullptr; - else - Operand = (TypeSourceInfo*)nullptr; - } - - /// Determine whether this typeid has a type operand which is potentially - /// evaluated, per C++11 [expr.typeid]p3. - bool isPotentiallyEvaluated() const; - - bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } - - /// \brief Retrieves the type operand of this typeid() expression after - /// various required adjustments (removing reference types, cv-qualifiers). - QualType getTypeOperand(ASTContext &Context) const; - - /// \brief Retrieve source information for the type operand. - TypeSourceInfo *getTypeOperandSourceInfo() const { - assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - return Operand.get<TypeSourceInfo *>(); - } - - void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { - assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - Operand = TSI; - } - - Expr *getExprOperand() const { - assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - return static_cast<Expr*>(Operand.get<Stmt *>()); - } - - void setExprOperand(Expr *E) { - assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - Operand = E; - } - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - void setSourceRange(SourceRange R) { Range = R; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXTypeidExprClass; - } - - // Iterators - child_range children() { - if (isTypeOperand()) - return child_range(child_iterator(), child_iterator()); - Stmt **begin = reinterpret_cast<Stmt**>(&Operand); - return child_range(begin, begin + 1); - } -}; - -/// \brief A member reference to an MSPropertyDecl. -/// -/// This expression always has pseudo-object type, and therefore it is -/// typically not encountered in a fully-typechecked expression except -/// within the syntactic form of a PseudoObjectExpr. -class MSPropertyRefExpr : public Expr { - Expr *BaseExpr; - MSPropertyDecl *TheDecl; - SourceLocation MemberLoc; - bool IsArrow; - NestedNameSpecifierLoc QualifierLoc; - -public: - MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, - QualType ty, ExprValueKind VK, - NestedNameSpecifierLoc qualifierLoc, - SourceLocation nameLoc) - : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, - /*type-dependent*/ false, baseExpr->isValueDependent(), - baseExpr->isInstantiationDependent(), - baseExpr->containsUnexpandedParameterPack()), - BaseExpr(baseExpr), TheDecl(decl), - MemberLoc(nameLoc), IsArrow(isArrow), - QualifierLoc(qualifierLoc) {} - - MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} - - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocStart(), getLocEnd()); - } - bool isImplicitAccess() const { - return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); - } - SourceLocation getLocStart() const { - if (!isImplicitAccess()) - return BaseExpr->getLocStart(); - else if (QualifierLoc) - return QualifierLoc.getBeginLoc(); - else - return MemberLoc; - } - SourceLocation getLocEnd() const { return getMemberLoc(); } - - child_range children() { - return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); - } - static bool classof(const Stmt *T) { - return T->getStmtClass() == MSPropertyRefExprClass; - } - - Expr *getBaseExpr() const { return BaseExpr; } - MSPropertyDecl *getPropertyDecl() const { return TheDecl; } - bool isArrow() const { return IsArrow; } - SourceLocation getMemberLoc() const { return MemberLoc; } - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - friend class ASTStmtReader; -}; - -/// MS property subscript expression. -/// MSVC supports 'property' attribute and allows to apply it to the -/// declaration of an empty array in a class or structure definition. -/// For example: -/// \code -/// __declspec(property(get=GetX, put=PutX)) int x[]; -/// \endcode -/// The above statement indicates that x[] can be used with one or more array -/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and -/// p->x[a][b] = i will be turned into p->PutX(a, b, i). -/// This is a syntactic pseudo-object expression. -class MSPropertySubscriptExpr : public Expr { - friend class ASTStmtReader; - enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; - Stmt *SubExprs[NUM_SUBEXPRS]; - SourceLocation RBracketLoc; - - void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } - void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } - -public: - MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, - ExprObjectKind OK, SourceLocation RBracketLoc) - : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), - Idx->isValueDependent(), Idx->isInstantiationDependent(), - Idx->containsUnexpandedParameterPack()), - RBracketLoc(RBracketLoc) { - SubExprs[BASE_EXPR] = Base; - SubExprs[IDX_EXPR] = Idx; - } - - /// \brief Create an empty array subscript expression. - explicit MSPropertySubscriptExpr(EmptyShell Shell) - : Expr(MSPropertySubscriptExprClass, Shell) {} - - Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); } - const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); } - - Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); } - const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); } - - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } - - SourceLocation getRBracketLoc() const { return RBracketLoc; } - void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - - SourceLocation getExprLoc() const LLVM_READONLY { - return getBase()->getExprLoc(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == MSPropertySubscriptExprClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); - } -}; - -/// 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()->isInstantiationDependentType(), - 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->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } - - CXXUuidofExpr(EmptyShell Empty, bool isExpr) - : Expr(CXXUuidofExprClass, Empty) { - if (isExpr) - Operand = (Expr*)nullptr; - else - Operand = (TypeSourceInfo*)nullptr; - } - - 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(ASTContext &Context) 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; - } - - StringRef getUuidAsStringRef(ASTContext &Context) const; - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - void setSourceRange(SourceRange R) { Range = R; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXUuidofExprClass; - } - - /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to - /// a single GUID. - static const UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = nullptr); - - // Iterators - child_range children() { - if (isTypeOperand()) - return child_range(child_iterator(), child_iterator()); - Stmt **begin = reinterpret_cast<Stmt**>(&Operand); - return child_range(begin, begin + 1); - } -}; - -/// \brief Represents the \c this expression in C++. -/// -/// This is a pointer to the object on which the current member function is -/// executing (C++ [expr.prim]p3). Example: -/// -/// \code -/// class Foo { -/// public: -/// void bar(); -/// void test() { this->bar(); } -/// }; -/// \endcode -class CXXThisExpr : public Expr { - SourceLocation Loc; - bool Implicit : 1; - -public: - CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) - : 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->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(L), Implicit(isImplicit) { } - - CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - bool isImplicit() const { return Implicit; } - void setImplicit(bool I) { Implicit = I; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXThisExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief A C++ throw-expression (C++ [except.throw]). -/// -/// This handles 'throw' (for re-throwing the current exception) and -/// 'throw' assignment-expression. When assignment-expression isn't -/// present, Op will be null. -class CXXThrowExpr : public Expr { - Stmt *Op; - SourceLocation ThrowLoc; - /// \brief Whether the thrown variable (if any) is in scope. - unsigned IsThrownVariableInScope : 1; - - friend class ASTStmtReader; - -public: - // \p Ty is the void type which is used as the result type of the - // expression. The \p l is the location of the throw keyword. \p expr - // can by null, if the optional expression to throw isn't present. - CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l, - bool IsThrownVariableInScope) : - Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - expr && expr->isInstantiationDependent(), - expr && expr->containsUnexpandedParameterPack()), - Op(expr), ThrowLoc(l), IsThrownVariableInScope(IsThrownVariableInScope) {} - CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} - - const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } - Expr *getSubExpr() { return cast_or_null<Expr>(Op); } - - SourceLocation getThrowLoc() const { return ThrowLoc; } - - /// \brief Determines whether the variable thrown by this expression (if any!) - /// is within the innermost try block. - /// - /// This information is required to determine whether the NRVO can apply to - /// this variable. - bool isThrownVariableInScope() const { return IsThrownVariableInScope; } - - SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - if (!getSubExpr()) - return ThrowLoc; - return getSubExpr()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXThrowExprClass; - } - - // Iterators - child_range children() { - return child_range(&Op, Op ? &Op+1 : &Op); - } -}; - -/// \brief A default argument (C++ [dcl.fct.default]). -/// -/// This wraps up a function call argument that was created from the -/// corresponding parameter's default argument, when the call did not -/// explicitly supply arguments for all of the parameters. -class CXXDefaultArgExpr final - : public Expr, - private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> { - /// \brief The parameter whose default is being used. - /// - /// When the bit is set, the subexpression is stored after the - /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's - /// actual default expression is the subexpression. - llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param; - - /// \brief The location where the default argument expression was used. - SourceLocation Loc; - - CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) - : Expr(SC, - param->hasUnparsedDefaultArg() - ? param->getType().getNonReferenceType() - : param->getDefaultArg()->getType(), - param->getDefaultArg()->getValueKind(), - param->getDefaultArg()->getObjectKind(), false, false, false, false), - Param(param, false), Loc(Loc) { } - - CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, - Expr *SubExpr) - : Expr(SC, SubExpr->getType(), - SubExpr->getValueKind(), SubExpr->getObjectKind(), - false, false, false, false), - Param(param, true), Loc(Loc) { - *getTrailingObjects<Expr *>() = SubExpr; - } - -public: - CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} - - // \p Param is the parameter whose default argument is used by this - // expression. - static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param) { - return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); - } - - // \p Param is the parameter whose default argument is used by this - // expression, and \p SubExpr is the expression that will actually be used. - static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, Expr *SubExpr); - - // Retrieve the parameter that the argument was created from. - const ParmVarDecl *getParam() const { return Param.getPointer(); } - ParmVarDecl *getParam() { return Param.getPointer(); } - - // Retrieve the actual argument to the function call. - const Expr *getExpr() const { - if (Param.getInt()) - return *getTrailingObjects<Expr *>(); - return getParam()->getDefaultArg(); - } - Expr *getExpr() { - if (Param.getInt()) - return *getTrailingObjects<Expr *>(); - return getParam()->getDefaultArg(); - } - - /// \brief Retrieve the location where this default argument was actually - /// used. - SourceLocation getUsedLocation() const { return Loc; } - - /// Default argument expressions have no representation in the - /// source, so they have an empty source range. - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } - - SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDefaultArgExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief A use of a default initializer in a constructor or in aggregate -/// initialization. -/// -/// This wraps a use of a C++ default initializer (technically, -/// a brace-or-equal-initializer for a non-static data member) when it -/// is implicitly used in a mem-initializer-list in a constructor -/// (C++11 [class.base.init]p8) or in aggregate initialization -/// (C++1y [dcl.init.aggr]p7). -class CXXDefaultInitExpr : public Expr { - /// \brief The field whose default is being used. - FieldDecl *Field; - - /// \brief The location where the default initializer expression was used. - SourceLocation Loc; - - CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, - QualType T); - - CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} - -public: - /// \p Field is the non-static data member whose default initializer is used - /// by this expression. - static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc, - FieldDecl *Field) { - return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); - } - - /// \brief Get the field whose initializer will be used. - FieldDecl *getField() { return Field; } - const FieldDecl *getField() const { return Field; } - - /// \brief Get the initialization expression that will be used. - const Expr *getExpr() const { - assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); - return Field->getInClassInitializer(); - } - Expr *getExpr() { - assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); - return Field->getInClassInitializer(); - } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDefaultInitExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend class ASTReader; - friend class ASTStmtReader; -}; - -/// \brief Represents a C++ temporary. -class CXXTemporary { - /// \brief The destructor that needs to be called. - const CXXDestructorDecl *Destructor; - - explicit CXXTemporary(const CXXDestructorDecl *destructor) - : Destructor(destructor) { } - -public: - static CXXTemporary *Create(const ASTContext &C, - const CXXDestructorDecl *Destructor); - - const CXXDestructorDecl *getDestructor() const { return Destructor; } - void setDestructor(const CXXDestructorDecl *Dtor) { - Destructor = Dtor; - } -}; - -/// \brief Represents binding an expression to a temporary. -/// -/// This ensures the destructor is called for the temporary. It should only be -/// needed for non-POD, non-trivially destructable class types. For example: -/// -/// \code -/// struct S { -/// S() { } // User defined constructor makes S non-POD. -/// ~S() { } // User defined destructor makes it non-trivial. -/// }; -/// void test() { -/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. -/// } -/// \endcode -class CXXBindTemporaryExpr : public Expr { - CXXTemporary *Temp; - - Stmt *SubExpr; - - CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) - : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), - VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), - SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - Temp(temp), SubExpr(SubExpr) { } - -public: - CXXBindTemporaryExpr(EmptyShell Empty) - : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {} - - static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, - Expr* SubExpr); - - CXXTemporary *getTemporary() { return Temp; } - const CXXTemporary *getTemporary() const { return Temp; } - void setTemporary(CXXTemporary *T) { Temp = T; } - - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - void setSubExpr(Expr *E) { SubExpr = E; } - - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} - - // Implement isa/cast/dyncast/etc. - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXBindTemporaryExprClass; - } - - // Iterators - child_range children() { return child_range(&SubExpr, &SubExpr + 1); } -}; - -/// \brief Represents a call to a C++ constructor. -class CXXConstructExpr : public Expr { -public: - enum ConstructionKind { - CK_Complete, - CK_NonVirtualBase, - CK_VirtualBase, - CK_Delegating - }; - -private: - CXXConstructorDecl *Constructor; - - SourceLocation Loc; - SourceRange ParenOrBraceRange; - unsigned NumArgs : 16; - bool Elidable : 1; - bool HadMultipleCandidates : 1; - bool ListInitialization : 1; - bool StdInitListInitialization : 1; - bool ZeroInitialization : 1; - unsigned ConstructKind : 2; - Stmt **Args; - -protected: - CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, - SourceLocation Loc, - CXXConstructorDecl *d, bool elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange); - - /// \brief Construct an empty C++ construction expression. - CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), - HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0), Args(nullptr) - { } - -public: - /// \brief Construct an empty C++ construction expression. - explicit CXXConstructExpr(EmptyShell Empty) - : Expr(CXXConstructExprClass, Empty), Constructor(nullptr), - NumArgs(0), Elidable(false), HadMultipleCandidates(false), - ListInitialization(false), ZeroInitialization(false), - ConstructKind(0), Args(nullptr) - { } - - static CXXConstructExpr *Create(const ASTContext &C, QualType T, - SourceLocation Loc, - CXXConstructorDecl *D, bool Elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange); - - CXXConstructorDecl *getConstructor() const { return Constructor; } - void setConstructor(CXXConstructorDecl *C) { Constructor = C; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation Loc) { this->Loc = Loc; } - - /// \brief Whether this construction is elidable. - bool isElidable() const { return Elidable; } - void setElidable(bool E) { Elidable = E; } - - /// \brief Whether the referred constructor was resolved from - /// an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { return HadMultipleCandidates; } - void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } - - /// \brief Whether this constructor call was written as list-initialization. - bool isListInitialization() const { return ListInitialization; } - void setListInitialization(bool V) { ListInitialization = V; } - - /// \brief Whether this constructor call was written as list-initialization, - /// but was interpreted as forming a std::initializer_list<T> from the list - /// and passing that as a single constructor argument. - /// See C++11 [over.match.list]p1 bullet 1. - bool isStdInitListInitialization() const { return StdInitListInitialization; } - void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } - - /// \brief Whether this construction first requires - /// zero-initialization before the initializer is called. - bool requiresZeroInitialization() const { return ZeroInitialization; } - void setRequiresZeroInitialization(bool ZeroInit) { - ZeroInitialization = ZeroInit; - } - - /// \brief Determine whether this constructor is actually constructing - /// a base class (rather than a complete object). - ConstructionKind getConstructionKind() const { - return (ConstructionKind)ConstructKind; - } - void setConstructionKind(ConstructionKind CK) { - ConstructKind = CK; - } - - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - typedef llvm::iterator_range<arg_iterator> arg_range; - typedef llvm::iterator_range<const_arg_iterator> arg_const_range; - - arg_range arguments() { return arg_range(arg_begin(), arg_end()); } - arg_const_range arguments() const { - return arg_const_range(arg_begin(), arg_end()); - } - - arg_iterator arg_begin() { return Args; } - arg_iterator arg_end() { return Args + NumArgs; } - const_arg_iterator arg_begin() const { return Args; } - const_arg_iterator arg_end() const { return Args + NumArgs; } - - Expr **getArgs() { return reinterpret_cast<Expr **>(Args); } - const Expr *const *getArgs() const { - return const_cast<CXXConstructExpr *>(this)->getArgs(); - } - unsigned getNumArgs() const { return NumArgs; } - - /// \brief Return the specified argument. - Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); - } - const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); - } - - /// \brief Set the specified argument. - void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); - Args[Arg] = ArgExpr; - } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } - void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXConstructExprClass || - T->getStmtClass() == CXXTemporaryObjectExprClass; - } - - // Iterators - child_range children() { - return child_range(&Args[0], &Args[0]+NumArgs); - } - - friend class ASTStmtReader; -}; - -/// \brief Represents an explicit C++ type conversion that uses "functional" -/// notation (C++ [expr.type.conv]). -/// -/// Example: -/// \code -/// x = int(0.5); -/// \endcode -class CXXFunctionalCastExpr final - : public ExplicitCastExpr, - private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { - SourceLocation LParenLoc; - SourceLocation RParenLoc; - - CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, - TypeSourceInfo *writtenTy, - CastKind kind, Expr *castExpr, unsigned pathSize, - SourceLocation lParenLoc, SourceLocation rParenLoc) - : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, - castExpr, pathSize, writtenTy), - LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} - - explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } - -public: - static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - TypeSourceInfo *Written, - CastKind Kind, Expr *Op, - const CXXCastPath *Path, - SourceLocation LPLoc, - SourceLocation RPLoc); - static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); - - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXFunctionalCastExprClass; - } - - friend TrailingObjects; - friend class CastExpr; -}; - -/// @brief Represents a C++ functional cast expression that builds a -/// temporary object. -/// -/// This expression type represents a C++ "functional" cast -/// (C++[expr.type.conv]) with N != 1 arguments that invokes a -/// constructor to build a temporary object. With N == 1 arguments the -/// functional cast expression will be represented by CXXFunctionalCastExpr. -/// Example: -/// \code -/// struct X { X(int, float); } -/// -/// X create_X() { -/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr -/// }; -/// \endcode -class CXXTemporaryObjectExpr : public CXXConstructExpr { - TypeSourceInfo *Type; - -public: - CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, - TypeSourceInfo *Type, - ArrayRef<Expr *> Args, - SourceRange ParenOrBraceRange, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization); - explicit CXXTemporaryObjectExpr(EmptyShell Empty) - : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } - - TypeSourceInfo *getTypeSourceInfo() const { return Type; } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXTemporaryObjectExprClass; - } - - friend class ASTStmtReader; -}; - -/// \brief A C++ lambda expression, which produces a function object -/// (of unspecified type) that can be invoked later. -/// -/// Example: -/// \code -/// void low_pass_filter(std::vector<double> &values, double cutoff) { -/// values.erase(std::remove_if(values.begin(), values.end(), -/// [=](double value) { return value > cutoff; }); -/// } -/// \endcode -/// -/// C++11 lambda expressions can capture local variables, either by copying -/// the values of those local variables at the time the function -/// object is constructed (not when it is called!) or by holding a -/// reference to the local variable. These captures can occur either -/// implicitly or can be written explicitly between the square -/// brackets ([...]) that start the lambda expression. -/// -/// C++1y introduces a new form of "capture" called an init-capture that -/// includes an initializing expression (rather than capturing a variable), -/// and which can never occur implicitly. -class LambdaExpr final - : public Expr, - private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> { - /// \brief The source range that covers the lambda introducer ([...]). - SourceRange IntroducerRange; - - /// \brief The source location of this lambda's capture-default ('=' or '&'). - SourceLocation CaptureDefaultLoc; - - /// \brief The number of captures. - unsigned NumCaptures : 16; - - /// \brief The default capture kind, which is a value of type - /// LambdaCaptureDefault. - unsigned CaptureDefault : 2; - - /// \brief Whether this lambda had an explicit parameter list vs. an - /// implicit (and empty) parameter list. - unsigned ExplicitParams : 1; - - /// \brief Whether this lambda had the result type explicitly specified. - unsigned ExplicitResultType : 1; - - /// \brief Whether there are any array index variables stored at the end of - /// this lambda expression. - unsigned HasArrayIndexVars : 1; - - /// \brief The location of the closing brace ('}') that completes - /// the lambda. - /// - /// The location of the brace is also available by looking up the - /// function call operator in the lambda class. However, it is - /// stored here to improve the performance of getSourceRange(), and - /// to avoid having to deserialize the function call operator from a - /// module file just to determine the source range. - SourceLocation ClosingBrace; - - size_t numTrailingObjects(OverloadToken<Stmt *>) const { - return NumCaptures + 1; - } - - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return HasArrayIndexVars ? NumCaptures + 1 : 0; - } - - /// \brief Construct a lambda expression. - LambdaExpr(QualType T, SourceRange IntroducerRange, - LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, - bool ExplicitParams, bool ExplicitResultType, - ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, - bool ContainsUnexpandedParameterPack); - - /// \brief Construct an empty lambda expression. - LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) - : Expr(LambdaExprClass, Empty), - NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), - ExplicitResultType(false), HasArrayIndexVars(true) { - getStoredStmts()[NumCaptures] = nullptr; - } - - Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } - - Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } - - /// \brief Retrieve the mapping from captures to the first array index - /// variable. - unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); } - - const unsigned *getArrayIndexStarts() const { - return getTrailingObjects<unsigned>(); - } - - /// \brief Retrieve the complete set of array-index variables. - VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); } - - VarDecl *const *getArrayIndexVars() const { - return getTrailingObjects<VarDecl *>(); - } - -public: - /// \brief Construct a new lambda expression. - static LambdaExpr * - Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, - LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, - ArrayRef<LambdaCapture> Captures, bool ExplicitParams, - bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, - bool ContainsUnexpandedParameterPack); - - /// \brief Construct a new lambda expression that will be deserialized from - /// an external source. - static LambdaExpr *CreateDeserialized(const ASTContext &C, - unsigned NumCaptures, - unsigned NumArrayIndexVars); - - /// \brief Determine the default capture kind for this lambda. - LambdaCaptureDefault getCaptureDefault() const { - return static_cast<LambdaCaptureDefault>(CaptureDefault); - } - - /// \brief Retrieve the location of this lambda's capture-default, if any. - SourceLocation getCaptureDefaultLoc() const { - return CaptureDefaultLoc; - } - - /// \brief Determine whether one of this lambda's captures is an init-capture. - bool isInitCapture(const LambdaCapture *Capture) const; - - /// \brief An iterator that walks over the captures of the lambda, - /// both implicit and explicit. - typedef const LambdaCapture *capture_iterator; - - /// \brief An iterator over a range of lambda captures. - typedef llvm::iterator_range<capture_iterator> capture_range; - - /// \brief Retrieve this lambda's captures. - capture_range captures() const; - - /// \brief Retrieve an iterator pointing to the first lambda capture. - capture_iterator capture_begin() const; - - /// \brief Retrieve an iterator pointing past the end of the - /// sequence of lambda captures. - capture_iterator capture_end() const; - - /// \brief Determine the number of captures in this lambda. - unsigned capture_size() const { return NumCaptures; } - - /// \brief Retrieve this lambda's explicit captures. - capture_range explicit_captures() const; - - /// \brief Retrieve an iterator pointing to the first explicit - /// lambda capture. - capture_iterator explicit_capture_begin() const; - - /// \brief Retrieve an iterator pointing past the end of the sequence of - /// explicit lambda captures. - capture_iterator explicit_capture_end() const; - - /// \brief Retrieve this lambda's implicit captures. - capture_range implicit_captures() const; - - /// \brief Retrieve an iterator pointing to the first implicit - /// lambda capture. - capture_iterator implicit_capture_begin() const; - - /// \brief Retrieve an iterator pointing past the end of the sequence of - /// implicit lambda captures. - capture_iterator implicit_capture_end() const; - - /// \brief Iterator that walks over the capture initialization - /// arguments. - typedef Expr **capture_init_iterator; - - /// \brief Const iterator that walks over the capture initialization - /// arguments. - typedef Expr *const *const_capture_init_iterator; - - /// \brief Retrieve the initialization expressions for this lambda's captures. - llvm::iterator_range<capture_init_iterator> capture_inits() { - return llvm::make_range(capture_init_begin(), capture_init_end()); - } - - /// \brief Retrieve the initialization expressions for this lambda's captures. - llvm::iterator_range<const_capture_init_iterator> capture_inits() const { - return llvm::make_range(capture_init_begin(), capture_init_end()); - } - - /// \brief Retrieve the first initialization argument for this - /// lambda expression (which initializes the first capture field). - capture_init_iterator capture_init_begin() { - return reinterpret_cast<Expr **>(getStoredStmts()); - } - - /// \brief Retrieve the first initialization argument for this - /// lambda expression (which initializes the first capture field). - const_capture_init_iterator capture_init_begin() const { - return reinterpret_cast<Expr *const *>(getStoredStmts()); - } - - /// \brief Retrieve the iterator pointing one past the last - /// initialization argument for this lambda expression. - capture_init_iterator capture_init_end() { - return capture_init_begin() + NumCaptures; - } - - /// \brief Retrieve the iterator pointing one past the last - /// initialization argument for this lambda expression. - const_capture_init_iterator capture_init_end() const { - return capture_init_begin() + NumCaptures; - } - - /// \brief Retrieve the set of index variables used in the capture - /// initializer of an array captured by copy. - /// - /// \param Iter The iterator that points at the capture initializer for - /// which we are extracting the corresponding index variables. - ArrayRef<VarDecl *> - getCaptureInitIndexVars(const_capture_init_iterator Iter) const; - - /// \brief Retrieve the source range covering the lambda introducer, - /// which contains the explicit capture list surrounded by square - /// brackets ([...]). - SourceRange getIntroducerRange() const { return IntroducerRange; } - - /// \brief Retrieve the class that corresponds to the lambda. - /// - /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the - /// captures in its fields and provides the various operations permitted - /// on a lambda (copying, calling). - CXXRecordDecl *getLambdaClass() const; - - /// \brief Retrieve the function call operator associated with this - /// lambda expression. - CXXMethodDecl *getCallOperator() const; - - /// \brief If this is a generic lambda expression, retrieve the template - /// parameter list associated with it, or else return null. - TemplateParameterList *getTemplateParameterList() const; - - /// \brief Whether this is a generic lambda. - bool isGenericLambda() const { return getTemplateParameterList(); } - - /// \brief Retrieve the body of the lambda. - CompoundStmt *getBody() const; - - /// \brief Determine whether the lambda is mutable, meaning that any - /// captures values can be modified. - bool isMutable() const; - - /// \brief Determine whether this lambda has an explicit parameter - /// list vs. an implicit (empty) parameter list. - bool hasExplicitParameters() const { return ExplicitParams; } - - /// \brief Whether this lambda had its result type explicitly specified. - bool hasExplicitResultType() const { return ExplicitResultType; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == LambdaExprClass; - } - - SourceLocation getLocStart() const LLVM_READONLY { - return IntroducerRange.getBegin(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; } - - child_range children() { - // Includes initialization exprs plus body stmt - return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// An expression "T()" which creates a value-initialized rvalue of type -/// T, which is a non-class type. See (C++98 [5.2.3p2]). -class CXXScalarValueInitExpr : public Expr { - SourceLocation RParenLoc; - TypeSourceInfo *TypeInfo; - - friend class ASTStmtReader; - -public: - /// \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, Type->isInstantiationDependentType(), - Type->containsUnexpandedParameterPack()), - RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} - - explicit CXXScalarValueInitExpr(EmptyShell Shell) - : Expr(CXXScalarValueInitExprClass, Shell) { } - - TypeSourceInfo *getTypeSourceInfo() const { - return TypeInfo; - } - - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXScalarValueInitExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief Represents a new-expression for memory allocation and constructor -/// calls, e.g: "new CXXNewExpr(foo)". -class CXXNewExpr : public Expr { - /// Contains an optional array size expression, an optional initialization - /// expression, and any number of optional placement arguments, in that order. - Stmt **SubExprs; - /// \brief Points to the allocation function used. - FunctionDecl *OperatorNew; - /// \brief Points to the deallocation function used in case of error. May be - /// null. - FunctionDecl *OperatorDelete; - - /// \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; - - /// \brief Range of the entire new expression. - SourceRange Range; - - /// \brief Source-range of a paren-delimited initializer. - SourceRange DirectInitRange; - - /// Was the usage ::new, i.e. is the global new to be used? - bool GlobalNew : 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 : 13; - /// What kind of initializer do we have? Could be none, parens, or braces. - /// In storage, we distinguish between "none, and no initializer expr", and - /// "none, but an implicit initializer expr". - unsigned StoredInitializationStyle : 2; - - friend class ASTStmtReader; - friend class ASTStmtWriter; -public: - enum InitializationStyle { - NoInit, ///< New-expression has no initializer as written. - CallInit, ///< New-expression has a C++98 paren-delimited initializer. - ListInit ///< New-expression has a C++11 list-initializer. - }; - - CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, - ArrayRef<Expr*> placementArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, Expr *initializer, - QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceRange Range, SourceRange directInitRange); - explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { } - - void AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer); - - QualType getAllocatedType() const { - assert(getType()->isPointerType()); - return getType()->getAs<PointerType>()->getPointeeType(); - } - - TypeSourceInfo *getAllocatedTypeSourceInfo() const { - return AllocatedTypeInfo; - } - - /// \brief True if the allocation result needs to be null-checked. - /// - /// C++11 [expr.new]p13: - /// If the allocation function returns null, initialization shall - /// not be done, the deallocation function shall not be called, - /// and the value of the new-expression shall be null. - /// - /// C++ DR1748: - /// If the allocation function is a reserved placement allocation - /// function that returns null, the behavior is undefined. - /// - /// An allocation function is not allowed to return null unless it - /// has a non-throwing exception-specification. The '03 rule is - /// identical except that the definition of a non-throwing - /// exception specification is just "is it throw()?". - bool shouldNullCheckAllocation(const ASTContext &Ctx) const; - - FunctionDecl *getOperatorNew() const { return OperatorNew; } - void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } - FunctionDecl *getOperatorDelete() const { return OperatorDelete; } - void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } - - bool isArray() const { return Array; } - Expr *getArraySize() { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; - } - const Expr *getArraySize() const { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; - } - - unsigned getNumPlacementArgs() const { return NumPlacementArgs; } - Expr **getPlacementArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); - } - - Expr *getPlacementArg(unsigned i) { - assert(i < NumPlacementArgs && "Index out of range"); - return getPlacementArgs()[i]; - } - const Expr *getPlacementArg(unsigned i) const { - assert(i < NumPlacementArgs && "Index out of range"); - return const_cast<CXXNewExpr*>(this)->getPlacementArg(i); - } - - bool isParenTypeId() const { return TypeIdParens.isValid(); } - SourceRange getTypeIdParens() const { return TypeIdParens; } - - bool isGlobalNew() const { return GlobalNew; } - - /// \brief Whether this new-expression has any initializer at all. - bool hasInitializer() const { return StoredInitializationStyle > 0; } - - /// \brief The kind of initializer this new-expression has. - InitializationStyle getInitializationStyle() const { - if (StoredInitializationStyle == 0) - return NoInit; - return static_cast<InitializationStyle>(StoredInitializationStyle-1); - } - - /// \brief The initializer of this new-expression. - Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; - } - const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; - } - - /// \brief Returns the CXXConstructExpr from this new-expression, or null. - const CXXConstructExpr* getConstructExpr() const { - return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); - } - - /// 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; - } - - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - - llvm::iterator_range<arg_iterator> placement_arguments() { - return llvm::make_range(placement_arg_begin(), placement_arg_end()); - } - - llvm::iterator_range<const_arg_iterator> placement_arguments() const { - return llvm::make_range(placement_arg_begin(), placement_arg_end()); - } - - arg_iterator placement_arg_begin() { - return SubExprs + Array + hasInitializer(); - } - arg_iterator placement_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); - } - const_arg_iterator placement_arg_begin() const { - return SubExprs + Array + hasInitializer(); - } - const_arg_iterator placement_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); - } - - typedef Stmt **raw_arg_iterator; - raw_arg_iterator raw_arg_begin() { return SubExprs; } - raw_arg_iterator raw_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); - } - const_arg_iterator raw_arg_begin() const { return SubExprs; } - const_arg_iterator raw_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); - } - - SourceLocation getStartLoc() const { return Range.getBegin(); } - SourceLocation getEndLoc() const { return Range.getEnd(); } - - SourceRange getDirectInitRange() const { return DirectInitRange; } - - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXNewExprClass; - } - - // Iterators - child_range children() { - return child_range(raw_arg_begin(), raw_arg_end()); - } -}; - -/// \brief Represents a \c delete expression for memory deallocation and -/// destructor calls, e.g. "delete[] pArray". -class CXXDeleteExpr : public Expr { - /// Points to the operator delete overload that is used. Could be a member. - FunctionDecl *OperatorDelete; - /// The pointer expression to be deleted. - Stmt *Argument; - /// Location of the expression. - SourceLocation Loc; - /// Is this a forced global delete, i.e. "::delete"? - 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; -public: - CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, - bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, - FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) - : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, - arg->isInstantiationDependent(), - arg->containsUnexpandedParameterPack()), - OperatorDelete(operatorDelete), Argument(arg), Loc(loc), - GlobalDelete(globalDelete), - ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } - explicit CXXDeleteExpr(EmptyShell Shell) - : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr), - Argument(nullptr) {} - - bool isGlobalDelete() const { return GlobalDelete; } - bool isArrayForm() const { return ArrayForm; } - 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; } - - Expr *getArgument() { return cast<Expr>(Argument); } - const Expr *getArgument() const { return cast<Expr>(Argument); } - - /// \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; - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY {return Argument->getLocEnd();} - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDeleteExprClass; - } - - // Iterators - child_range children() { return child_range(&Argument, &Argument+1); } - - friend class ASTStmtReader; -}; - -/// \brief Stores the type being destroyed by a pseudo-destructor expression. -class PseudoDestructorTypeStorage { - /// \brief Either the type source information or the name of the type, if - /// it couldn't be resolved due to type-dependence. - llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; - - /// \brief The starting source location of the pseudo-destructor type. - SourceLocation Location; - -public: - PseudoDestructorTypeStorage() { } - - PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) - : Type(II), Location(Loc) { } - - PseudoDestructorTypeStorage(TypeSourceInfo *Info); - - TypeSourceInfo *getTypeSourceInfo() const { - return Type.dyn_cast<TypeSourceInfo *>(); - } - - IdentifierInfo *getIdentifier() const { - return Type.dyn_cast<IdentifierInfo *>(); - } - - SourceLocation getLocation() const { return Location; } -}; - -/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). -/// -/// A pseudo-destructor is an expression that looks like a member access to a -/// destructor of a scalar type, except that scalar types don't have -/// destructors. For example: -/// -/// \code -/// typedef int T; -/// void f(int *p) { -/// p->T::~T(); -/// } -/// \endcode -/// -/// Pseudo-destructors typically occur when instantiating templates such as: -/// -/// \code -/// template<typename T> -/// void destroy(T* ptr) { -/// ptr->T::~T(); -/// } -/// \endcode -/// -/// for scalar types. A pseudo-destructor expression has no run-time semantics -/// beyond evaluating the base expression. -class CXXPseudoDestructorExpr : public Expr { - /// \brief The base expression (that is being destroyed). - Stmt *Base; - - /// \brief Whether the operator was an arrow ('->'); otherwise, it was a - /// period ('.'). - bool IsArrow : 1; - - /// \brief The location of the '.' or '->' operator. - SourceLocation OperatorLoc; - - /// \brief The nested-name-specifier that follows the operator, if present. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The type that precedes the '::' in a qualified pseudo-destructor - /// expression. - TypeSourceInfo *ScopeType; - - /// \brief The location of the '::' in a qualified pseudo-destructor - /// expression. - SourceLocation ColonColonLoc; - - /// \brief The location of the '~'. - SourceLocation TildeLoc; - - /// \brief The type being destroyed, or its name if we were unable to - /// resolve the name. - PseudoDestructorTypeStorage DestroyedType; - - friend class ASTStmtReader; - -public: - CXXPseudoDestructorExpr(const ASTContext &Context, - Expr *Base, bool isArrow, SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - TypeSourceInfo *ScopeType, - SourceLocation ColonColonLoc, - SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType); - - explicit CXXPseudoDestructorExpr(EmptyShell Shell) - : Expr(CXXPseudoDestructorExprClass, Shell), - Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { } - - Expr *getBase() const { return cast<Expr>(Base); } - - /// \brief Determines whether this member expression actually had - /// a C++ nested-name-specifier prior to the name of the member, e.g., - /// x->Base::foo. - bool hasQualifier() const { return QualifierLoc.hasQualifier(); } - - /// \brief Retrieves the nested-name-specifier that qualifies the type name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief If the member name was qualified, retrieves the - /// nested-name-specifier that precedes the member name. Otherwise, returns - /// null. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief Determine whether this pseudo-destructor expression was written - /// using an '->' (otherwise, it used a '.'). - bool isArrow() const { return IsArrow; } - - /// \brief Retrieve the location of the '.' or '->' operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } - - /// \brief Retrieve the scope type in a qualified pseudo-destructor - /// expression. - /// - /// Pseudo-destructor expressions can have extra qualification within them - /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). - /// Here, if the object type of the expression is (or may be) a scalar type, - /// \p T may also be a scalar type and, therefore, cannot be part of a - /// nested-name-specifier. It is stored as the "scope type" of the pseudo- - /// destructor expression. - TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } - - /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor - /// expression. - SourceLocation getColonColonLoc() const { return ColonColonLoc; } - - /// \brief Retrieve the location of the '~'. - SourceLocation getTildeLoc() const { return TildeLoc; } - - /// \brief Retrieve the source location information for the type - /// being destroyed. - /// - /// This type-source information is available for non-dependent - /// pseudo-destructor expressions and some dependent pseudo-destructor - /// expressions. Returns null if we only have the identifier for a - /// dependent pseudo-destructor expression. - TypeSourceInfo *getDestroyedTypeInfo() const { - return DestroyedType.getTypeSourceInfo(); - } - - /// \brief In a dependent pseudo-destructor expression for which we do not - /// have full type information on the destroyed type, provides the name - /// of the destroyed type. - IdentifierInfo *getDestroyedTypeIdentifier() const { - return DestroyedType.getIdentifier(); - } - - /// \brief Retrieve the type being destroyed. - QualType getDestroyedType() const; - - /// \brief Retrieve the starting location of the type being destroyed. - SourceLocation getDestroyedTypeLoc() const { - return DestroyedType.getLocation(); - } - - /// \brief Set the name of destroyed type for a dependent pseudo-destructor - /// expression. - void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { - DestroyedType = PseudoDestructorTypeStorage(II, Loc); - } - - /// \brief Set the destroyed type. - void setDestroyedType(TypeSourceInfo *Info) { - DestroyedType = PseudoDestructorTypeStorage(Info); - } - - SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();} - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXPseudoDestructorExprClass; - } - - // Iterators - child_range children() { return child_range(&Base, &Base + 1); } -}; - -/// \brief A type trait used in the implementation of various C++11 and -/// Library TR1 trait templates. -/// -/// \code -/// __is_pod(int) == true -/// __is_enum(std::string) == false -/// __is_trivially_constructible(vector<int>, int*, int*) -/// \endcode -class TypeTraitExpr final - : public Expr, - private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> { - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing parenthesis. - SourceLocation RParenLoc; - - // Note: The TypeSourceInfos for the arguments are allocated after the - // TypeTraitExpr. - - TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, - ArrayRef<TypeSourceInfo *> Args, - SourceLocation RParenLoc, - bool Value); - - TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } - - size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { - return getNumArgs(); - } - -public: - /// \brief Create a new type trait expression. - static TypeTraitExpr *Create(const ASTContext &C, QualType T, - SourceLocation Loc, TypeTrait Kind, - ArrayRef<TypeSourceInfo *> Args, - SourceLocation RParenLoc, - bool Value); - - static TypeTraitExpr *CreateDeserialized(const ASTContext &C, - unsigned NumArgs); - - /// \brief Determine which type trait this expression uses. - TypeTrait getTrait() const { - return static_cast<TypeTrait>(TypeTraitExprBits.Kind); - } - - bool getValue() const { - assert(!isValueDependent()); - return TypeTraitExprBits.Value; - } - - /// \brief Determine the number of arguments to this type trait. - unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } - - /// \brief Retrieve the Ith argument. - TypeSourceInfo *getArg(unsigned I) const { - assert(I < getNumArgs() && "Argument out-of-range"); - return getArgs()[I]; - } - - /// \brief Retrieve the argument types. - ArrayRef<TypeSourceInfo *> getArgs() const { - return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(), - getNumArgs()); - } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == TypeTraitExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief An Embarcadero array type trait, as used in the implementation of -/// __array_rank and __array_extent. -/// -/// Example: -/// \code -/// __array_rank(int[10][20]) == 2 -/// __array_extent(int, 1) == 20 -/// \endcode -class ArrayTypeTraitExpr : public Expr { - virtual void anchor(); - - /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned. - unsigned ATT : 2; - - /// \brief The value of the type trait. Unspecified if dependent. - uint64_t Value; - - /// \brief The array dimension being queried, or -1 if not used. - Expr *Dimension; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The type being queried. - TypeSourceInfo *QueriedType; - -public: - ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, - TypeSourceInfo *queried, uint64_t value, - Expr *dimension, SourceLocation rparen, QualType ty) - : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, - false, queried->getType()->isDependentType(), - (queried->getType()->isInstantiationDependentType() || - (dimension && dimension->isInstantiationDependent())), - queried->getType()->containsUnexpandedParameterPack()), - ATT(att), Value(value), Dimension(dimension), - Loc(loc), RParen(rparen), QueriedType(queried) { } - - - explicit ArrayTypeTraitExpr(EmptyShell Empty) - : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), - QueriedType() { } - - virtual ~ArrayTypeTraitExpr() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } - - QualType getQueriedType() const { return QueriedType->getType(); } - - TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } - - uint64_t getValue() const { assert(!isTypeDependent()); return Value; } - - Expr *getDimensionExpression() const { return Dimension; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ArrayTypeTraitExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend class ASTStmtReader; -}; - -/// \brief An expression trait intrinsic. -/// -/// Example: -/// \code -/// __is_lvalue_expr(std::cout) == true -/// __is_lvalue_expr(1) == false -/// \endcode -class ExpressionTraitExpr : public Expr { - /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned. - unsigned ET : 31; - /// \brief The value of the type trait. Unspecified if dependent. - bool Value : 1; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The expression being queried. - Expr* QueriedExpression; -public: - ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, - Expr *queried, bool value, - SourceLocation rparen, QualType resultType) - : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, - false, // Not type-dependent - // Value-dependent if the argument is type-dependent. - queried->isTypeDependent(), - queried->isInstantiationDependent(), - queried->containsUnexpandedParameterPack()), - ET(et), Value(value), Loc(loc), RParen(rparen), - QueriedExpression(queried) { } - - explicit ExpressionTraitExpr(EmptyShell Empty) - : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), - QueriedExpression() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } - - Expr *getQueriedExpression() const { return QueriedExpression; } - - bool getValue() const { return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ExpressionTraitExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend class ASTStmtReader; -}; - - -/// \brief A reference to an overloaded function set, either an -/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. -class OverloadExpr : public Expr { - /// \brief The common name of these declarations. - DeclarationNameInfo NameInfo; - - /// \brief The nested-name-specifier that qualifies the name, if any. - NestedNameSpecifierLoc QualifierLoc; - - /// The results. These are undesugared, which is to say, they may - /// include UsingShadowDecls. Access is relative to the naming - /// class. - // FIXME: Allocate this data after the OverloadExpr subclass. - DeclAccessPair *Results; - unsigned NumResults; - -protected: - /// \brief Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo; - - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo * - getTrailingASTTemplateKWAndArgsInfo(); // defined far below. - - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { - return const_cast<OverloadExpr *>(this) - ->getTrailingASTTemplateKWAndArgsInfo(); - } - - /// Return the optional template arguments. - TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below - - OverloadExpr(StmtClass K, const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent, - bool KnownInstantiationDependent, - bool KnownContainsUnexpandedParameterPack); - - OverloadExpr(StmtClass K, EmptyShell Empty) - : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0), - HasTemplateKWAndArgsInfo(false) { } - - void initializeResults(const ASTContext &C, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End); - -public: - struct FindResult { - OverloadExpr *Expression; - bool IsAddressOfOperand; - bool HasFormOfMemberPointer; - }; - - /// \brief Finds the overloaded expression in the given expression \p E of - /// OverloadTy. - /// - /// \return the expression (which must be there) and true if it has - /// the particular form of a member pointer expression - static FindResult find(Expr *E) { - assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); - - FindResult Result; - - E = E->IgnoreParens(); - if (isa<UnaryOperator>(E)) { - assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); - E = cast<UnaryOperator>(E)->getSubExpr(); - OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens()); - - Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); - Result.IsAddressOfOperand = true; - Result.Expression = Ovl; - } else { - Result.HasFormOfMemberPointer = false; - Result.IsAddressOfOperand = false; - Result.Expression = cast<OverloadExpr>(E); - } - - return Result; - } - - /// \brief Gets the naming class of this lookup, if any. - CXXRecordDecl *getNamingClass() const; - - typedef UnresolvedSetImpl::iterator decls_iterator; - decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } - decls_iterator decls_end() const { - return UnresolvedSetIterator(Results + NumResults); - } - llvm::iterator_range<decls_iterator> decls() const { - return llvm::make_range(decls_begin(), decls_end()); - } - - /// \brief Gets the number of declarations in the unresolved set. - unsigned getNumDecls() const { return NumResults; } - - /// \brief Gets the full name info. - const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - - /// \brief Gets the name looked up. - DeclarationName getName() const { return NameInfo.getName(); } - - /// \brief Gets the location of the name. - SourceLocation getNameLoc() const { return NameInfo.getLoc(); } - - /// \brief Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief Fetches the nested-name qualifier with source-location - /// information, if one was given. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the location of the template keyword preceding - /// this name, if any. - SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; - } - - /// \brief Retrieve the location of the left angle bracket starting the - /// explicit template argument list following the name, if any. - SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; - } - - /// \brief Retrieve the location of the right angle bracket ending the - /// explicit template argument list following the name, if any. - SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; - } - - /// \brief Determines whether the name was preceded by the template keyword. - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - - /// \brief Determines whether this expression had explicit template arguments. - bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - - TemplateArgumentLoc const *getTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return nullptr; - return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); - } - - unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return 0; - - return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; - } - - /// \brief Copies the template arguments into the given structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgs()) - getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnresolvedLookupExprClass || - T->getStmtClass() == UnresolvedMemberExprClass; - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief A reference to a name which we were able to look up during -/// parsing but could not resolve to a specific declaration. -/// -/// This arises in several ways: -/// * we might be waiting for argument-dependent lookup; -/// * the name might resolve to an overloaded function; -/// and eventually: -/// * the lookup might have included a function template. -/// -/// These never include UnresolvedUsingValueDecls, which are always class -/// members and therefore appear only in UnresolvedMemberLookupExprs. -class UnresolvedLookupExpr final - : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { - /// True if these lookup results should be extended by - /// argument-dependent lookup if this is the operand of a function - /// call. - bool RequiresADL; - - /// True if these lookup results are overloaded. This is pretty - /// trivially rederivable if we urgently need to kill this field. - bool Overloaded; - - /// The naming class (C++ [class.access.base]p5) of the lookup, if - /// any. This can generally be recalculated from the context chain, - /// but that can be fairly expensive for unqualified lookups. If we - /// want to improve memory use here, this could go in a union - /// against the qualified-lookup bits. - CXXRecordDecl *NamingClass; - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - - UnresolvedLookupExpr(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, - NameInfo, TemplateArgs, Begin, End, false, false, false), - RequiresADL(RequiresADL), - Overloaded(Overloaded), NamingClass(NamingClass) - {} - - UnresolvedLookupExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(nullptr) - {} - - friend TrailingObjects; - friend class OverloadExpr; - friend class ASTStmtReader; - -public: - static UnresolvedLookupExpr *Create(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, - bool ADL, bool Overloaded, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, - SourceLocation(), NameInfo, - ADL, Overloaded, nullptr, Begin, End); - } - - static UnresolvedLookupExpr *Create(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool ADL, - const TemplateArgumentListInfo *Args, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End); - - static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); - - /// True if this declaration should be extended by - /// argument-dependent lookup. - bool requiresADL() const { return RequiresADL; } - - /// True if this lookup is overloaded. - bool isOverloaded() const { return Overloaded; } - - /// Gets the 'naming class' (in the sense of C++0x - /// [class.access.base]p5) of the lookup. This is the scope - /// that was looked in to find these results. - CXXRecordDecl *getNamingClass() const { return NamingClass; } - - SourceLocation getLocStart() const LLVM_READONLY { - if (NestedNameSpecifierLoc l = getQualifierLoc()) - return l.getBeginLoc(); - return getNameInfo().getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - if (hasExplicitTemplateArgs()) - return getRAngleLoc(); - return getNameInfo().getLocEnd(); - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnresolvedLookupExprClass; - } -}; - -/// \brief A qualified reference to a name whose declaration cannot -/// yet be resolved. -/// -/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that -/// it expresses a reference to a declaration such as -/// X<T>::value. The difference, however, is that an -/// DependentScopeDeclRefExpr node is used only within C++ templates when -/// the qualification (e.g., X<T>::) refers to a dependent type. In -/// this case, X<T>::value cannot resolve to a declaration because the -/// declaration will differ from one instantiation of X<T> to the -/// next. Therefore, DependentScopeDeclRefExpr keeps track of the -/// qualifier (X<T>::) and the name of the entity being referenced -/// ("value"). Such expressions will instantiate to a DeclRefExpr once the -/// declaration can be found. -class DependentScopeDeclRefExpr final - : public Expr, - private llvm::TrailingObjects<DependentScopeDeclRefExpr, - ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { - /// \brief The nested-name-specifier that qualifies this unresolved - /// declaration name. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The name of the entity we will be referencing. - DeclarationNameInfo NameInfo; - - /// \brief Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo; - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - - DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *Args); - -public: - static DependentScopeDeclRefExpr *Create(const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); - - static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); - - /// \brief Retrieve the name that this expression refers to. - const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - - /// \brief Retrieve the name that this expression refers to. - DeclarationName getDeclName() const { return NameInfo.getName(); } - - /// \brief Retrieve the location of the name within the expression. - /// - /// For example, in "X<T>::value" this is the location of "value". - SourceLocation getLocation() const { return NameInfo.getLoc(); } - - /// \brief Retrieve the nested-name-specifier that qualifies the - /// name, with source location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies this - /// declaration. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief Retrieve the location of the template keyword preceding - /// this name, if any. - SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; - } - - /// \brief Retrieve the location of the left angle bracket starting the - /// explicit template argument list following the name, if any. - SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; - } - - /// \brief Retrieve the location of the right angle bracket ending the - /// explicit template argument list following the name, if any. - SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; - } - - /// Determines whether the name was preceded by the template keyword. - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - - /// Determines whether this lookup had explicit template arguments. - bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - - /// \brief Copies the template arguments (if present) into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgs()) - getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( - getTrailingObjects<TemplateArgumentLoc>(), List); - } - - TemplateArgumentLoc const *getTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return nullptr; - - return getTrailingObjects<TemplateArgumentLoc>(); - } - - unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return 0; - - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; - } - - /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, - /// and differs from getLocation().getStart(). - SourceLocation getLocStart() const LLVM_READONLY { - return QualifierLoc.getBeginLoc(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - if (hasExplicitTemplateArgs()) - return getRAngleLoc(); - return getLocation(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DependentScopeDeclRefExprClass; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// Represents an expression -- generally a full-expression -- that -/// 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 kinds of -/// expressions can create cleanups, including basically every -/// call in ARC that returns an Objective-C pointer. -/// -/// This expression also tracks whether the sub-expression contains a -/// potentially-evaluated block literal. The lifetime of a block -/// literal is the extent of the enclosing scope. -class ExprWithCleanups final - : public Expr, - private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> { -public: - /// The type of objects that are kept in the cleanup. - /// It's useful to remember the set of blocks; we could also - /// remember the set of temporaries, but there's currently - /// no need. - typedef BlockDecl *CleanupObject; - -private: - Stmt *SubExpr; - - ExprWithCleanups(EmptyShell, unsigned NumObjects); - ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects); - - friend TrailingObjects; - friend class ASTStmtReader; - -public: - static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty, - unsigned numObjects); - - static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr, - ArrayRef<CleanupObject> objects); - - ArrayRef<CleanupObject> getObjects() const { - return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(), - getNumObjects()); - } - - unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } - - CleanupObject getObject(unsigned i) const { - assert(i < getNumObjects() && "Index out of range"); - return getObjects()[i]; - } - - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - - /// As with any mutator of the AST, be very careful - /// when modifying an existing AST to preserve its invariants. - void setSubExpr(Expr *E) { SubExpr = E; } - - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} - - // Implement isa/cast/dyncast/etc. - static bool classof(const Stmt *T) { - return T->getStmtClass() == ExprWithCleanupsClass; - } - - // Iterators - child_range children() { return child_range(&SubExpr, &SubExpr + 1); } -}; - -/// \brief Describes an explicit type conversion that uses functional -/// notion but could not be resolved because one or more arguments are -/// type-dependent. -/// -/// The explicit type conversions expressed by -/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>, -/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and -/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is -/// type-dependent. For example, this would occur in a template such -/// as: -/// -/// \code -/// template<typename T, typename A1> -/// inline T make_a(const A1& a1) { -/// return T(a1); -/// } -/// \endcode -/// -/// When the returned expression is instantiated, it may resolve to a -/// constructor call, conversion function call, or some kind of type -/// conversion. -class CXXUnresolvedConstructExpr final - : public Expr, - private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> { - /// \brief The type being constructed. - TypeSourceInfo *Type; - - /// \brief The location of the left parentheses ('('). - SourceLocation LParenLoc; - - /// \brief The location of the right parentheses (')'). - SourceLocation RParenLoc; - - /// \brief The number of arguments used to construct the type. - unsigned NumArgs; - - CXXUnresolvedConstructExpr(TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc); - - CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { } - - friend TrailingObjects; - friend class ASTStmtReader; - -public: - static CXXUnresolvedConstructExpr *Create(const ASTContext &C, - TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc); - - static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, - unsigned NumArgs); - - /// \brief Retrieve the type that is being constructed, as specified - /// in the source code. - 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; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - - /// \brief Retrieve the location of the right parentheses (')') that - /// follows the argument list. - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - /// \brief Retrieve the number of arguments. - unsigned arg_size() const { return NumArgs; } - - typedef Expr** arg_iterator; - arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } - arg_iterator arg_end() { return arg_begin() + NumArgs; } - - typedef const Expr* const * const_arg_iterator; - const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } - const_arg_iterator arg_end() const { - return arg_begin() + NumArgs; - } - - Expr *getArg(unsigned I) { - assert(I < NumArgs && "Argument index out-of-range"); - return *(arg_begin() + I); - } - - const Expr *getArg(unsigned I) const { - assert(I < NumArgs && "Argument index out-of-range"); - return *(arg_begin() + I); - } - - void setArg(unsigned I, Expr *E) { - assert(I < NumArgs && "Argument index out-of-range"); - *(arg_begin() + I) = E; - } - - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY { - if (!RParenLoc.isValid() && NumArgs > 0) - return getArg(NumArgs - 1)->getLocEnd(); - return RParenLoc; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXUnresolvedConstructExprClass; - } - - // Iterators - child_range children() { - Stmt **begin = reinterpret_cast<Stmt **>(arg_begin()); - return child_range(begin, begin + NumArgs); - } -}; - -/// \brief Represents a C++ member access expression where the actual -/// member referenced could not be resolved because the base -/// expression or the member name was dependent. -/// -/// Like UnresolvedMemberExprs, these can be either implicit or -/// explicit accesses. It is only possible to get one of these with -/// an implicit access if a qualifier is provided. -class CXXDependentScopeMemberExpr final - : public Expr, - private llvm::TrailingObjects<CXXDependentScopeMemberExpr, - ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { - /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. Can be null in implicit accesses. - Stmt *Base; - - /// \brief The type of the base expression. Never null, even for - /// implicit accesses. - QualType BaseType; - - /// \brief Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// \brief Whether this member expression has info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo : 1; - - /// \brief The location of the '->' or '.' operator. - SourceLocation OperatorLoc; - - /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief In a qualified member access expression such as t->Base::f, this - /// member stores the resolves of name lookup in the context of the member - /// access expression, to be used at instantiation time. - /// - /// FIXME: This member, along with the QualifierLoc, could - /// be stuck into a structure that is optionally allocated at the end of - /// the CXXDependentScopeMemberExpr, to save space in the common case. - NamedDecl *FirstQualifierFoundInScope; - - /// \brief The member to which this member expression refers, which - /// can be name, overloaded operator, or destructor. - /// - /// FIXME: could also be a template-id - DeclarationNameInfo MemberNameInfo; - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, - QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs); - -public: - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, - QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo); - - static CXXDependentScopeMemberExpr * - Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs); - - static CXXDependentScopeMemberExpr * - CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, - 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 - /// location of the operator is invalid in this case. - bool isImplicitAccess() const; - - /// \brief Retrieve the base object of this member expressions, - /// e.g., the \c x in \c x.m. - Expr *getBase() const { - assert(!isImplicitAccess()); - return cast<Expr>(Base); - } - - QualType getBaseType() const { return BaseType; } - - /// \brief Determine whether this member expression used the '->' - /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } - - /// \brief Retrieve the location of the '->' or '.' operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } - - /// \brief Retrieve the nested-name-specifier that qualifies the member - /// name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief Retrieve the nested-name-specifier that qualifies the member - /// name, with source location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - - /// \brief Retrieve the first part of the nested-name-specifier that was - /// found in the scope of the member access expression when the member access - /// was initially parsed. - /// - /// This function only returns a useful result when member access expression - /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration - /// returned by this function describes what was found by unqualified name - /// lookup for the identifier "Base" within the scope of the member access - /// expression itself. At template instantiation time, this information is - /// combined with the results of name lookup into the type of the object - /// expression itself (the class type of x). - NamedDecl *getFirstQualifierFoundInScope() const { - return FirstQualifierFoundInScope; - } - - /// \brief Retrieve the name of the member that this expression - /// refers to. - const DeclarationNameInfo &getMemberNameInfo() const { - return MemberNameInfo; - } - - /// \brief Retrieve the name of the member that this expression - /// refers to. - DeclarationName getMember() const { return MemberNameInfo.getName(); } - - // \brief Retrieve the location of the name of the member that this - // expression refers to. - SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } - - /// \brief Retrieve the location of the template keyword preceding the - /// member name, if any. - SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; - } - - /// \brief Retrieve the location of the left angle bracket starting the - /// explicit template argument list following the member name, if any. - SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; - } - - /// \brief Retrieve the location of the right angle bracket ending the - /// explicit template argument list following the member name, if any. - SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; - } - - /// Determines whether the member name was preceded by the template keyword. - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - - /// \brief Copies the template arguments (if present) into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgs()) - getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( - getTrailingObjects<TemplateArgumentLoc>(), List); - } - - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return nullptr; - - return getTrailingObjects<TemplateArgumentLoc>(); - } - - /// \brief Retrieve the number of template arguments provided as part of this - /// template-id. - unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgs()) - return 0; - - return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; - } - - SourceLocation getLocStart() const LLVM_READONLY { - if (!isImplicitAccess()) - return Base->getLocStart(); - if (getQualifier()) - return getQualifierLoc().getBeginLoc(); - return MemberNameInfo.getBeginLoc(); - } - - SourceLocation getLocEnd() const LLVM_READONLY { - if (hasExplicitTemplateArgs()) - return getRAngleLoc(); - return MemberNameInfo.getEndLoc(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXDependentScopeMemberExprClass; - } - - // Iterators - child_range children() { - if (isImplicitAccess()) - return child_range(child_iterator(), child_iterator()); - return child_range(&Base, &Base + 1); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// \brief Represents a C++ member access expression for which lookup -/// produced a set of overloaded functions. -/// -/// The member access may be explicit or implicit: -/// \code -/// struct A { -/// int a, b; -/// int explicitAccess() { return this->a + this->A::b; } -/// int implicitAccess() { return a + A::b; } -/// }; -/// \endcode -/// -/// In the final AST, an explicit access always becomes a MemberExpr. -/// An implicit access may become either a MemberExpr or a -/// DeclRefExpr, depending on whether the member is static. -class UnresolvedMemberExpr final - : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { - /// \brief Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// \brief Whether the lookup results contain an unresolved using - /// declaration. - bool HasUnresolvedUsing : 1; - - /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. - /// - /// This can be null if this is an 'unbased' member expression. - Stmt *Base; - - /// \brief The type of the base expression; never null. - QualType BaseType; - - /// \brief The location of the '->' or '.' operator. - SourceLocation OperatorLoc; - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - - UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); - - UnresolvedMemberExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false), Base(nullptr) { } - - friend TrailingObjects; - friend class OverloadExpr; - friend class ASTStmtReader; - -public: - static UnresolvedMemberExpr * - Create(const ASTContext &C, bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); - - static UnresolvedMemberExpr * - CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, - 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 location of the operator is invalid in this case. - bool isImplicitAccess() const; - - /// \brief Retrieve the base object of this member expressions, - /// e.g., the \c x in \c x.m. - Expr *getBase() { - assert(!isImplicitAccess()); - return cast<Expr>(Base); - } - const Expr *getBase() const { - assert(!isImplicitAccess()); - return cast<Expr>(Base); - } - - QualType getBaseType() const { return BaseType; } - - /// \brief Determine whether the lookup results contain an unresolved using - /// declaration. - bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } - - /// \brief Determine whether this member expression used the '->' - /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } - - /// \brief Retrieve the location of the '->' or '.' operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } - - /// \brief Retrieve the naming class of this lookup. - CXXRecordDecl *getNamingClass() const; - - /// \brief Retrieve the full name info for the member that this expression - /// refers to. - const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - - /// \brief Retrieve the name of the member that this expression - /// refers to. - DeclarationName getMemberName() const { return getName(); } - - // \brief Retrieve the location of the name of the member that this - // expression refers to. - SourceLocation getMemberLoc() const { return getNameLoc(); } - - // \brief Return the preferred location (the member name) for the arrow when - // diagnosing a problem with this expression. - SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); } - - SourceLocation getLocStart() const LLVM_READONLY { - if (!isImplicitAccess()) - return Base->getLocStart(); - if (NestedNameSpecifierLoc l = getQualifierLoc()) - return l.getBeginLoc(); - return getMemberNameInfo().getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - if (hasExplicitTemplateArgs()) - return getRAngleLoc(); - return getMemberNameInfo().getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnresolvedMemberExprClass; - } - - // Iterators - child_range children() { - if (isImplicitAccess()) - return child_range(child_iterator(), child_iterator()); - return child_range(&Base, &Base + 1); - } -}; - -inline ASTTemplateKWAndArgsInfo * -OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) - return nullptr; - - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - else - return cast<UnresolvedMemberExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); -} - -inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this) - ->getTrailingObjects<TemplateArgumentLoc>(); - else - return cast<UnresolvedMemberExpr>(this) - ->getTrailingObjects<TemplateArgumentLoc>(); -} - -/// \brief Represents a C++11 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, - Val == CT_Dependent || Operand->isInstantiationDependent(), - 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); } - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - - bool getValue() const { return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXNoexceptExprClass; - } - - // Iterators - child_range children() { return child_range(&Operand, &Operand + 1); } -}; - -/// \brief Represents a C++11 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, - Optional<unsigned> NumExpansions) - : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), - Pattern->getObjectKind(), /*TypeDependent=*/true, - /*ValueDependent=*/true, /*InstantiationDependent=*/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. - Optional<unsigned> getNumExpansions() const { - if (NumExpansions) - return NumExpansions - 1; - - return None; - } - - SourceLocation getLocStart() const LLVM_READONLY { - return Pattern->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PackExpansionExprClass; - } - - // Iterators - child_range children() { - return child_range(&Pattern, &Pattern + 1); - } -}; - - -/// \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 final - : public Expr, - private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> { - /// \brief The location of the \c 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 not value-dependent, this is the length of - /// the pack. When the expression was parsed rather than instantiated - /// (and thus is value-dependent), this is zero. - /// - /// After partial substitution into a sizeof...(X) expression (for instance, - /// within an alias template or during function template argument deduction), - /// we store a trailing array of partially-substituted TemplateArguments, - /// and this is the length of that array. - unsigned Length; - - /// \brief The parameter pack. - NamedDecl *Pack; - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; - - /// \brief Create an expression that computes the length of - /// the given parameter pack. - SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, - SourceLocation PackLoc, SourceLocation RParenLoc, - Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/!Length, - /*InstantiationDependent=*/!Length, - /*ContainsUnexpandedParameterPack=*/false), - OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), - Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { - assert((!Length || PartialArgs.empty()) && - "have partial args for non-dependent sizeof... expression"); - TemplateArgument *Args = getTrailingObjects<TemplateArgument>(); - std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); - } - - /// \brief Create an empty expression. - SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) - : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {} - -public: - static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc, - NamedDecl *Pack, SourceLocation PackLoc, - SourceLocation RParenLoc, - Optional<unsigned> Length = None, - ArrayRef<TemplateArgument> PartialArgs = None); - static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, - unsigned NumPartialArgs); - - /// \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; - } - - /// \brief Determine whether this represents a partially-substituted sizeof... - /// expression, such as is produced for: - /// - /// template<typename ...Ts> using X = int[sizeof...(Ts)]; - /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>); - bool isPartiallySubstituted() const { - return isValueDependent() && Length; - } - - /// \brief Get - ArrayRef<TemplateArgument> getPartialArguments() const { - assert(isPartiallySubstituted()); - const TemplateArgument *Args = getTrailingObjects<TemplateArgument>(); - return llvm::makeArrayRef(Args, Args + Length); - } - - SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SizeOfPackExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief Represents a reference to a non-type template parameter -/// that has been substituted with a template argument. -class SubstNonTypeTemplateParmExpr : public Expr { - /// \brief The replaced parameter. - NonTypeTemplateParmDecl *Param; - - /// \brief The replacement expression. - Stmt *Replacement; - - /// \brief The location of the non-type template parameter reference. - SourceLocation NameLoc; - - friend class ASTReader; - friend class ASTStmtReader; - explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) - : Expr(SubstNonTypeTemplateParmExprClass, Empty) { } - -public: - SubstNonTypeTemplateParmExpr(QualType type, - ExprValueKind valueKind, - SourceLocation loc, - NonTypeTemplateParmDecl *param, - Expr *replacement) - : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary, - replacement->isTypeDependent(), replacement->isValueDependent(), - replacement->isInstantiationDependent(), - replacement->containsUnexpandedParameterPack()), - Param(param), Replacement(replacement), NameLoc(loc) {} - - SourceLocation getNameLoc() const { return NameLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } - - Expr *getReplacement() const { return cast<Expr>(Replacement); } - - NonTypeTemplateParmDecl *getParameter() const { return Param; } - - static bool classof(const Stmt *s) { - return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; - } - - // Iterators - child_range children() { return child_range(&Replacement, &Replacement+1); } -}; - -/// \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 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 ASTReader; - friend class ASTStmtReader; - explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) - : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } - -public: - SubstNonTypeTemplateParmPackExpr(QualType T, - NonTypeTemplateParmDecl *Param, - SourceLocation NameLoc, - const TemplateArgument &ArgPack); - - /// \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; - - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief Represents a reference to a function parameter pack that has been -/// substituted but not yet expanded. -/// -/// When a pack expansion contains multiple parameter packs at different levels, -/// this node is used to represent a function parameter pack at an outer level -/// which we have already substituted to refer to expanded parameters, but where -/// the containing pack expansion cannot yet be expanded. -/// -/// \code -/// template<typename...Ts> struct S { -/// template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...)); -/// }; -/// template struct S<int, int>; -/// \endcode -class FunctionParmPackExpr final - : public Expr, - private llvm::TrailingObjects<FunctionParmPackExpr, ParmVarDecl *> { - /// \brief The function parameter pack which was referenced. - ParmVarDecl *ParamPack; - - /// \brief The location of the function parameter pack reference. - SourceLocation NameLoc; - - /// \brief The number of expansions of this pack. - unsigned NumParameters; - - FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, - SourceLocation NameLoc, unsigned NumParams, - ParmVarDecl *const *Params); - - friend TrailingObjects; - friend class ASTReader; - friend class ASTStmtReader; - -public: - static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, - ParmVarDecl *ParamPack, - SourceLocation NameLoc, - ArrayRef<ParmVarDecl *> Params); - static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, - unsigned NumParams); - - /// \brief Get the parameter pack which this expression refers to. - ParmVarDecl *getParameterPack() const { return ParamPack; } - - /// \brief Get the location of the parameter pack. - SourceLocation getParameterPackLocation() const { return NameLoc; } - - /// \brief Iterators over the parameters which the parameter pack expanded - /// into. - typedef ParmVarDecl * const *iterator; - iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); } - iterator end() const { return begin() + NumParameters; } - - /// \brief Get the number of parameters in this parameter pack. - unsigned getNumExpansions() const { return NumParameters; } - - /// \brief Get an expansion of the parameter pack by index. - ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; } - - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == FunctionParmPackExprClass; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief Represents a prvalue temporary that is written into memory so that -/// a reference can bind to it. -/// -/// Prvalue expressions are materialized when they need to have an address -/// in memory for a reference to bind to. This happens when binding a -/// reference to the result of a conversion, e.g., -/// -/// \code -/// const int &r = 1.0; -/// \endcode -/// -/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is -/// then materialized via a \c MaterializeTemporaryExpr, and the reference -/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues -/// (either an lvalue or an xvalue, depending on the kind of reference binding -/// to it), maintaining the invariant that references always bind to glvalues. -/// -/// Reference binding and copy-elision can both extend the lifetime of a -/// temporary. When either happens, the expression will also track the -/// declaration which is responsible for the lifetime extension. -class MaterializeTemporaryExpr : public Expr { -private: - struct ExtraState { - /// \brief The temporary-generating expression whose value will be - /// materialized. - Stmt *Temporary; - - /// \brief The declaration which lifetime-extended this reference, if any. - /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. - const ValueDecl *ExtendingDecl; - - unsigned ManglingNumber; - }; - llvm::PointerUnion<Stmt *, ExtraState *> State; - - friend class ASTStmtReader; - friend class ASTStmtWriter; - - void initializeExtraState(const ValueDecl *ExtendedBy, - unsigned ManglingNumber); - -public: - MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference) - : Expr(MaterializeTemporaryExprClass, T, - BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, - Temporary->isTypeDependent(), Temporary->isValueDependent(), - Temporary->isInstantiationDependent(), - Temporary->containsUnexpandedParameterPack()), - State(Temporary) {} - - MaterializeTemporaryExpr(EmptyShell Empty) - : Expr(MaterializeTemporaryExprClass, Empty) { } - - Stmt *getTemporary() const { - return State.is<Stmt *>() ? State.get<Stmt *>() - : State.get<ExtraState *>()->Temporary; - } - - /// \brief Retrieve the temporary-generating subexpression whose value will - /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); } - - /// \brief Retrieve the storage duration for the materialized temporary. - StorageDuration getStorageDuration() const { - const ValueDecl *ExtendingDecl = getExtendingDecl(); - if (!ExtendingDecl) - return SD_FullExpression; - // FIXME: This is not necessarily correct for a temporary materialized - // within a default initializer. - if (isa<FieldDecl>(ExtendingDecl)) - return SD_Automatic; - return cast<VarDecl>(ExtendingDecl)->getStorageDuration(); - } - - /// \brief Get the declaration which triggered the lifetime-extension of this - /// temporary, if any. - const ValueDecl *getExtendingDecl() const { - return State.is<Stmt *>() ? nullptr - : State.get<ExtraState *>()->ExtendingDecl; - } - - void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); - - unsigned getManglingNumber() const { - return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber; - } - - /// \brief Determine whether this materialized temporary is bound to an - /// lvalue reference; otherwise, it's bound to an rvalue reference. - bool isBoundToLvalueReference() const { - return getValueKind() == VK_LValue; - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getTemporary()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getTemporary()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == MaterializeTemporaryExprClass; - } - - // Iterators - child_range children() { - if (State.is<Stmt *>()) - return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1); - - auto ES = State.get<ExtraState *>(); - return child_range(&ES->Temporary, &ES->Temporary + 1); - } -}; - -/// \brief Represents a folding of a pack over an operator. -/// -/// This expression is always dependent and represents a pack expansion of the -/// forms: -/// -/// ( expr op ... ) -/// ( ... op expr ) -/// ( expr op ... op expr ) -class CXXFoldExpr : public Expr { - SourceLocation LParenLoc; - SourceLocation EllipsisLoc; - SourceLocation RParenLoc; - Stmt *SubExprs[2]; - BinaryOperatorKind Opcode; - - friend class ASTStmtReader; - friend class ASTStmtWriter; -public: - CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, - BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc) - : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary, - /*Dependent*/ true, true, true, - /*ContainsUnexpandedParameterPack*/ false), - LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), - Opcode(Opcode) { - SubExprs[0] = LHS; - SubExprs[1] = RHS; - } - CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} - - Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); } - Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); } - - /// Does this produce a right-associated sequence of operators? - bool isRightFold() const { - return getLHS() && getLHS()->containsUnexpandedParameterPack(); - } - /// Does this produce a left-associated sequence of operators? - bool isLeftFold() const { return !isRightFold(); } - /// Get the pattern, that is, the operand that contains an unexpanded pack. - Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); } - /// Get the operand that doesn't contain a pack, for a binary fold. - Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); } - - SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - BinaryOperatorKind getOperator() const { return Opcode; } - - SourceLocation getLocStart() const LLVM_READONLY { - return LParenLoc; - } - SourceLocation getLocEnd() const LLVM_READONLY { - return RParenLoc; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXFoldExprClass; - } - - // Iterators - child_range children() { return child_range(SubExprs, SubExprs + 2); } -}; - -/// \brief Represents an expression that might suspend coroutine execution; -/// either a co_await or co_yield expression. -/// -/// Evaluation of this expression first evaluates its 'ready' expression. If -/// that returns 'false': -/// -- execution of the coroutine is suspended -/// -- the 'suspend' expression is evaluated -/// -- if the 'suspend' expression returns 'false', the coroutine is -/// resumed -/// -- otherwise, control passes back to the resumer. -/// If the coroutine is not suspended, or when it is resumed, the 'resume' -/// expression is evaluated, and its result is the result of the overall -/// expression. -class CoroutineSuspendExpr : public Expr { - SourceLocation KeywordLoc; - - enum SubExpr { Common, Ready, Suspend, Resume, Count }; - Stmt *SubExprs[SubExpr::Count]; - - friend class ASTStmtReader; -public: - CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, - Expr *Ready, Expr *Suspend, Expr *Resume) - : Expr(SC, Resume->getType(), Resume->getValueKind(), - Resume->getObjectKind(), Resume->isTypeDependent(), - Resume->isValueDependent(), Common->isInstantiationDependent(), - Common->containsUnexpandedParameterPack()), - KeywordLoc(KeywordLoc) { - SubExprs[SubExpr::Common] = Common; - SubExprs[SubExpr::Ready] = Ready; - SubExprs[SubExpr::Suspend] = Suspend; - SubExprs[SubExpr::Resume] = Resume; - } - CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, - Expr *Common) - : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true, - Common->containsUnexpandedParameterPack()), - KeywordLoc(KeywordLoc) { - assert(Common->isTypeDependent() && Ty->isDependentType() && - "wrong constructor for non-dependent co_await/co_yield expression"); - SubExprs[SubExpr::Common] = Common; - SubExprs[SubExpr::Ready] = nullptr; - SubExprs[SubExpr::Suspend] = nullptr; - SubExprs[SubExpr::Resume] = nullptr; - } - CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { - SubExprs[SubExpr::Common] = nullptr; - SubExprs[SubExpr::Ready] = nullptr; - SubExprs[SubExpr::Suspend] = nullptr; - SubExprs[SubExpr::Resume] = nullptr; - } - - SourceLocation getKeywordLoc() const { return KeywordLoc; } - Expr *getCommonExpr() const { - return static_cast<Expr*>(SubExprs[SubExpr::Common]); - } - - Expr *getReadyExpr() const { - return static_cast<Expr*>(SubExprs[SubExpr::Ready]); - } - Expr *getSuspendExpr() const { - return static_cast<Expr*>(SubExprs[SubExpr::Suspend]); - } - Expr *getResumeExpr() const { - return static_cast<Expr*>(SubExprs[SubExpr::Resume]); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return KeywordLoc; - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getCommonExpr()->getLocEnd(); - } - - child_range children() { - return child_range(SubExprs, SubExprs + SubExpr::Count); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CoawaitExprClass || - T->getStmtClass() == CoyieldExprClass; - } -}; - -/// \brief Represents a 'co_await' expression. -class CoawaitExpr : public CoroutineSuspendExpr { - friend class ASTStmtReader; -public: - CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume) - : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready, - Suspend, Resume) {} - CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand) - : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {} - CoawaitExpr(EmptyShell Empty) - : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} - - Expr *getOperand() const { - // FIXME: Dig out the actual operand or store it. - return getCommonExpr(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CoawaitExprClass; - } -}; - -/// \brief Represents a 'co_yield' expression. -class CoyieldExpr : public CoroutineSuspendExpr { - friend class ASTStmtReader; -public: - CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume) - : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready, - Suspend, Resume) {} - CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand) - : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {} - CoyieldExpr(EmptyShell Empty) - : CoroutineSuspendExpr(CoyieldExprClass, Empty) {} - - Expr *getOperand() const { - // FIXME: Dig out the actual operand or store it. - return getCommonExpr(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CoyieldExprClass; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h deleted file mode 100644 index 61e6383..0000000 --- a/include/clang/AST/ExprObjC.h +++ /dev/null @@ -1,1568 +0,0 @@ -//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 ExprObjC interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_EXPROBJC_H -#define LLVM_CLANG_AST_EXPROBJC_H - -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/SelectorLocationsKind.h" -#include "clang/Basic/IdentifierTable.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - class IdentifierInfo; - class ASTContext; - -/// ObjCStringLiteral, used for Objective-C string literals -/// i.e. @"foo". -class ObjCStringLiteral : public Expr { - Stmt *String; - SourceLocation AtLoc; -public: - ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) - : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - String(SL), AtLoc(L) {} - explicit ObjCStringLiteral(EmptyShell Empty) - : Expr(ObjCStringLiteralClass, Empty) {} - - StringLiteral *getString() { return cast<StringLiteral>(String); } - const StringLiteral *getString() const { return cast<StringLiteral>(String); } - void setString(StringLiteral *S) { String = S; } - - SourceLocation getAtLoc() const { return AtLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCStringLiteralClass; - } - - // Iterators - child_range children() { return child_range(&String, &String+1); } -}; - -/// ObjCBoolLiteralExpr - Objective-C Boolean Literal. -/// -class ObjCBoolLiteralExpr : public Expr { - bool Value; - SourceLocation Loc; -public: - ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), Value(val), Loc(l) {} - - explicit ObjCBoolLiteralExpr(EmptyShell Empty) - : Expr(ObjCBoolLiteralExprClass, Empty) { } - - bool getValue() const { return Value; } - void setValue(bool V) { Value = V; } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCBoolLiteralExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// ObjCBoxedExpr - used for generalized expression boxing. -/// as in: @(strdup("hello world")), @(random()) or @(view.frame) -/// Also used for boxing non-parenthesized numeric literals; -/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc). -class ObjCBoxedExpr : public Expr { - Stmt *SubExpr; - ObjCMethodDecl *BoxingMethod; - SourceRange Range; -public: - ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, - SourceRange R) - : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, - E->isTypeDependent(), E->isValueDependent(), - E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), - SubExpr(E), BoxingMethod(method), Range(R) {} - explicit ObjCBoxedExpr(EmptyShell Empty) - : Expr(ObjCBoxedExprClass, Empty) {} - - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - - ObjCMethodDecl *getBoxingMethod() const { - return BoxingMethod; - } - - SourceLocation getAtLoc() const { return Range.getBegin(); } - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCBoxedExprClass; - } - - // Iterators - child_range children() { return child_range(&SubExpr, &SubExpr+1); } - - typedef ConstExprIterator const_arg_iterator; - - const_arg_iterator arg_begin() const { - return reinterpret_cast<Stmt const * const*>(&SubExpr); - } - const_arg_iterator arg_end() const { - return reinterpret_cast<Stmt const * const*>(&SubExpr + 1); - } - - friend class ASTStmtReader; -}; - -/// ObjCArrayLiteral - used for objective-c array containers; as in: -/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]]; -class ObjCArrayLiteral final - : public Expr, - private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> { - unsigned NumElements; - SourceRange Range; - ObjCMethodDecl *ArrayWithObjectsMethod; - - ObjCArrayLiteral(ArrayRef<Expr *> Elements, - QualType T, ObjCMethodDecl * Method, - SourceRange SR); - - explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements) - : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} - -public: - static ObjCArrayLiteral *Create(const ASTContext &C, - ArrayRef<Expr *> Elements, - QualType T, ObjCMethodDecl * Method, - SourceRange SR); - - static ObjCArrayLiteral *CreateEmpty(const ASTContext &C, - unsigned NumElements); - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCArrayLiteralClass; - } - - /// \brief Retrieve elements of array of literals. - Expr **getElements() { return getTrailingObjects<Expr *>(); } - - /// \brief Retrieve elements of array of literals. - const Expr * const *getElements() const { - return getTrailingObjects<Expr *>(); - } - - /// getNumElements - Return number of elements of objective-c array literal. - unsigned getNumElements() const { return NumElements; } - - /// getExpr - Return the Expr at the specified index. - Expr *getElement(unsigned Index) { - assert((Index < NumElements) && "Arg access out of range!"); - return cast<Expr>(getElements()[Index]); - } - const Expr *getElement(unsigned Index) const { - assert((Index < NumElements) && "Arg access out of range!"); - return cast<Expr>(getElements()[Index]); - } - - ObjCMethodDecl *getArrayWithObjectsMethod() const { - return ArrayWithObjectsMethod; - } - - // Iterators - child_range children() { - return child_range(reinterpret_cast<Stmt **>(getElements()), - reinterpret_cast<Stmt **>(getElements()) + NumElements); - } - - friend TrailingObjects; - friend class ASTStmtReader; -}; - -/// \brief An element in an Objective-C dictionary literal. -/// -struct ObjCDictionaryElement { - /// \brief The key for the dictionary element. - Expr *Key; - - /// \brief The value of the dictionary element. - Expr *Value; - - /// \brief The location of the ellipsis, if this is a pack expansion. - SourceLocation EllipsisLoc; - - /// \brief The number of elements this pack expansion will expand to, if - /// this is a pack expansion and is known. - Optional<unsigned> NumExpansions; - - /// \brief Determines whether this dictionary element is a pack expansion. - bool isPackExpansion() const { return EllipsisLoc.isValid(); } -}; -} // end namespace clang - -namespace llvm { -template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {}; -} - -namespace clang { -/// \brief Internal struct for storing Key/value pair. -struct ObjCDictionaryLiteral_KeyValuePair { - Expr *Key; - Expr *Value; -}; - -/// \brief Internal struct to describes an element that is a pack -/// expansion, used if any of the elements in the dictionary literal -/// are pack expansions. -struct ObjCDictionaryLiteral_ExpansionData { - /// \brief The location of the ellipsis, if this element is a pack - /// expansion. - SourceLocation EllipsisLoc; - - /// \brief If non-zero, the number of elements that this pack - /// expansion will expand to (+1). - unsigned NumExpansionsPlusOne; -}; - -/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary -/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; -class ObjCDictionaryLiteral final - : public Expr, - private llvm::TrailingObjects<ObjCDictionaryLiteral, - ObjCDictionaryLiteral_KeyValuePair, - ObjCDictionaryLiteral_ExpansionData> { - /// \brief The number of elements in this dictionary literal. - unsigned NumElements : 31; - - /// \brief Determine whether this dictionary literal has any pack expansions. - /// - /// If the dictionary literal has pack expansions, then there will - /// be an array of pack expansion data following the array of - /// key/value pairs, which provide the locations of the ellipses (if - /// any) and number of elements in the expansion (if known). If - /// there are no pack expansions, we optimize away this storage. - unsigned HasPackExpansions : 1; - - SourceRange Range; - ObjCMethodDecl *DictWithObjectsMethod; - - typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair; - typedef ObjCDictionaryLiteral_ExpansionData ExpansionData; - - size_t numTrailingObjects(OverloadToken<KeyValuePair>) const { - return NumElements; - } - - ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, - bool HasPackExpansions, - QualType T, ObjCMethodDecl *method, - SourceRange SR); - - explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements, - bool HasPackExpansions) - : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements), - HasPackExpansions(HasPackExpansions) {} - -public: - static ObjCDictionaryLiteral *Create(const ASTContext &C, - ArrayRef<ObjCDictionaryElement> VK, - bool HasPackExpansions, - QualType T, ObjCMethodDecl *method, - SourceRange SR); - - static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C, - unsigned NumElements, - bool HasPackExpansions); - - /// getNumElements - Return number of elements of objective-c dictionary - /// literal. - unsigned getNumElements() const { return NumElements; } - - ObjCDictionaryElement getKeyValueElement(unsigned Index) const { - assert((Index < NumElements) && "Arg access out of range!"); - const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index]; - ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None }; - if (HasPackExpansions) { - const ExpansionData &Expansion = - getTrailingObjects<ExpansionData>()[Index]; - Result.EllipsisLoc = Expansion.EllipsisLoc; - if (Expansion.NumExpansionsPlusOne > 0) - Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1; - } - return Result; - } - - ObjCMethodDecl *getDictWithObjectsMethod() const - { return DictWithObjectsMethod; } - - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCDictionaryLiteralClass; - } - - // Iterators - child_range children() { - // Note: we're taking advantage of the layout of the KeyValuePair struct - // here. If that struct changes, this code will need to change as well. - static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2, - "KeyValuePair is expected size"); - return child_range( - reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()), - reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) + - NumElements * 2); - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; -}; - - -/// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same -/// type and behavior as StringLiteral except that the string initializer is -/// obtained from ASTContext with the encoding type as an argument. -class ObjCEncodeExpr : public Expr { - TypeSourceInfo *EncodedType; - SourceLocation AtLoc, RParenLoc; -public: - ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, - SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isInstantiationDependentType(), - EncodedType->getType()->containsUnexpandedParameterPack()), - EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} - - explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} - - - SourceLocation getAtLoc() const { return AtLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - QualType getEncodedType() const { return EncodedType->getType(); } - - TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } - void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { - EncodedType = EncType; - } - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCEncodeExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// ObjCSelectorExpr used for \@selector in Objective-C. -class ObjCSelectorExpr : public Expr { - Selector SelName; - SourceLocation AtLoc, RParenLoc; -public: - ObjCSelectorExpr(QualType T, Selector selInfo, - SourceLocation at, SourceLocation rp) - : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - SelName(selInfo), AtLoc(at), RParenLoc(rp){} - explicit ObjCSelectorExpr(EmptyShell Empty) - : Expr(ObjCSelectorExprClass, Empty) {} - - Selector getSelector() const { return SelName; } - void setSelector(Selector S) { SelName = S; } - - SourceLocation getAtLoc() const { return AtLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - /// getNumArgs - Return the number of actual arguments to this call. - unsigned getNumArgs() const { return SelName.getNumArgs(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCSelectorExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// ObjCProtocolExpr used for protocol expression in Objective-C. -/// -/// This is used as: \@protocol(foo), as in: -/// \code -/// [obj conformsToProtocol:@protocol(foo)] -/// \endcode -/// -/// The return type is "Protocol*". -class ObjCProtocolExpr : public Expr { - ObjCProtocolDecl *TheProtocol; - SourceLocation AtLoc, ProtoLoc, RParenLoc; -public: - ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, - SourceLocation at, SourceLocation protoLoc, SourceLocation rp) - : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} - explicit ObjCProtocolExpr(EmptyShell Empty) - : Expr(ObjCProtocolExprClass, Empty) {} - - ObjCProtocolDecl *getProtocol() const { return TheProtocol; } - void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } - - SourceLocation getProtocolIdLoc() const { return ProtoLoc; } - SourceLocation getAtLoc() const { return AtLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCProtocolExprClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// ObjCIvarRefExpr - A reference to an ObjC instance variable. -class ObjCIvarRefExpr : public Expr { - ObjCIvarDecl *D; - Stmt *Base; - SourceLocation Loc; - /// OpLoc - This is the location of '.' or '->' - SourceLocation OpLoc; - - bool IsArrow:1; // True if this is "X->F", false if this is "X.F". - bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). - -public: - ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, - SourceLocation l, SourceLocation oploc, - Expr *base, - bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, VK_LValue, - d->isBitField() ? OK_BitField : OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - D(d), Base(base), Loc(l), OpLoc(oploc), - IsArrow(arrow), IsFreeIvar(freeIvar) {} - - explicit ObjCIvarRefExpr(EmptyShell Empty) - : Expr(ObjCIvarRefExprClass, Empty) {} - - ObjCIvarDecl *getDecl() { return D; } - const ObjCIvarDecl *getDecl() const { return D; } - void setDecl(ObjCIvarDecl *d) { D = d; } - - const Expr *getBase() const { return cast<Expr>(Base); } - Expr *getBase() { return cast<Expr>(Base); } - void setBase(Expr * base) { Base = base; } - - bool isArrow() const { return IsArrow; } - bool isFreeIvar() const { return IsFreeIvar; } - void setIsArrow(bool A) { IsArrow = A; } - void setIsFreeIvar(bool A) { IsFreeIvar = A; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { - return isFreeIvar() ? Loc : getBase()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - SourceLocation getOpLoc() const { return OpLoc; } - void setOpLoc(SourceLocation L) { OpLoc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCIvarRefExprClass; - } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } -}; - -/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC -/// property. -class ObjCPropertyRefExpr : public Expr { -private: - /// 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; - - /// \brief Indicates whether the property reference will result in a message - /// to the getter, the setter, or both. - /// This applies to both implicit and explicit property references. - enum MethodRefFlags { - MethodRef_None = 0, - MethodRef_Getter = 0x1, - MethodRef_Setter = 0x2 - }; - - /// \brief Contains the Setter method pointer and MethodRefFlags bit flags. - llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags; - - // FIXME: Maybe we should store the property identifier here, - // because it's not rederivable from the other data when there's an - // implicit property with no getter (because the 'foo' -> 'setFoo:' - // transformation is lossy on the first character). - - SourceLocation IdLoc; - - /// \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, VK, OK, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), - IdLoc(l), ReceiverLoc(), Receiver(base) { - assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); - } - - ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation l, SourceLocation sl, QualType st) - : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, false, st->isInstantiationDependentType(), - st->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), - IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { - assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); - } - - ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, - QualType T, ExprValueKind VK, ExprObjectKind OK, - SourceLocation IdLoc, Expr *Base) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, - Base->isValueDependent(), Base->isInstantiationDependent(), - Base->containsUnexpandedParameterPack()), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { - assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); - } - - 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, false), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { - assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); - } - - 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, false), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { - assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); - } - - explicit ObjCPropertyRefExpr(EmptyShell Empty) - : Expr(ObjCPropertyRefExprClass, Empty) {} - - bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } - bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } - - 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 SetterAndMethodRefFlags.getPointer(); - } - - Selector getGetterSelector() const { - if (isImplicitProperty()) - return getImplicitPropertyGetter()->getSelector(); - return getExplicitProperty()->getGetterName(); - } - - Selector getSetterSelector() const { - if (isImplicitProperty()) - return getImplicitPropertySetter()->getSelector(); - return getExplicitProperty()->getSetterName(); - } - - /// \brief True if the property reference will result in a message to the - /// getter. - /// This applies to both implicit and explicit property references. - bool isMessagingGetter() const { - return SetterAndMethodRefFlags.getInt() & MethodRef_Getter; - } - - /// \brief True if the property reference will result in a message to the - /// setter. - /// This applies to both implicit and explicit property references. - bool isMessagingSetter() const { - return SetterAndMethodRefFlags.getInt() & MethodRef_Setter; - } - - void setIsMessagingGetter(bool val = true) { - setMethodRefFlag(MethodRef_Getter, val); - } - - void setIsMessagingSetter(bool val = true) { - setMethodRefFlag(MethodRef_Setter, val); - } - - const Expr *getBase() const { - return cast<Expr>(Receiver.get<Stmt*>()); - } - Expr *getBase() { - return cast<Expr>(Receiver.get<Stmt*>()); - } - - SourceLocation getLocation() const { return IdLoc; } - - 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*>(); } - - /// Determine the type of the base, regardless of the kind of receiver. - QualType getReceiverType(const ASTContext &ctx) const; - - SourceLocation getLocStart() const LLVM_READONLY { - return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCPropertyRefExprClass; - } - - // Iterators - child_range children() { - if (Receiver.is<Stmt*>()) { - Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! - return child_range(begin, begin+1); - } - return child_range(child_iterator(), child_iterator()); - } - -private: - friend class ASTStmtReader; - friend class ASTStmtWriter; - void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { - PropertyOrGetter.setPointer(D); - PropertyOrGetter.setInt(false); - SetterAndMethodRefFlags.setPointer(nullptr); - SetterAndMethodRefFlags.setInt(methRefFlags); - } - void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, - unsigned methRefFlags) { - PropertyOrGetter.setPointer(Getter); - PropertyOrGetter.setInt(true); - SetterAndMethodRefFlags.setPointer(Setter); - SetterAndMethodRefFlags.setInt(methRefFlags); - } - void setBase(Expr *Base) { Receiver = Base; } - void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } - void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; } - - void setLocation(SourceLocation L) { IdLoc = L; } - void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; } - - void setMethodRefFlag(MethodRefFlags flag, bool val) { - unsigned f = SetterAndMethodRefFlags.getInt(); - if (val) - f |= flag; - else - f &= ~flag; - SetterAndMethodRefFlags.setInt(f); - } -}; - -/// ObjCSubscriptRefExpr - used for array and dictionary subscripting. -/// array[4] = array[3]; dictionary[key] = dictionary[alt_key]; -/// -class ObjCSubscriptRefExpr : public Expr { - // Location of ']' in an indexing expression. - SourceLocation RBracket; - // array/dictionary base expression. - // for arrays, this is a numeric expression. For dictionaries, this is - // an objective-c object pointer expression. - enum { BASE, KEY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; - - ObjCMethodDecl *GetAtIndexMethodDecl; - - // For immutable objects this is null. When ObjCSubscriptRefExpr is to read - // an indexed object this is null too. - ObjCMethodDecl *SetAtIndexMethodDecl; - -public: - - ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, - ExprValueKind VK, ExprObjectKind OK, - ObjCMethodDecl *getMethod, - ObjCMethodDecl *setMethod, SourceLocation RB) - : Expr(ObjCSubscriptRefExprClass, T, VK, OK, - base->isTypeDependent() || key->isTypeDependent(), - base->isValueDependent() || key->isValueDependent(), - base->isInstantiationDependent() || key->isInstantiationDependent(), - (base->containsUnexpandedParameterPack() || - key->containsUnexpandedParameterPack())), - RBracket(RB), - GetAtIndexMethodDecl(getMethod), - SetAtIndexMethodDecl(setMethod) - {SubExprs[BASE] = base; SubExprs[KEY] = key;} - - explicit ObjCSubscriptRefExpr(EmptyShell Empty) - : Expr(ObjCSubscriptRefExprClass, Empty) {} - - SourceLocation getRBracket() const { return RBracket; } - void setRBracket(SourceLocation RB) { RBracket = RB; } - - SourceLocation getLocStart() const LLVM_READONLY { - return SubExprs[BASE]->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCSubscriptRefExprClass; - } - - Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); } - void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; } - - Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); } - void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; } - - ObjCMethodDecl *getAtIndexMethodDecl() const { - return GetAtIndexMethodDecl; - } - - ObjCMethodDecl *setAtIndexMethodDecl() const { - return SetAtIndexMethodDecl; - } - - bool isArraySubscriptRefExpr() const { - return getKeyExpr()->getType()->isIntegralOrEnumerationType(); - } - - child_range children() { - return child_range(SubExprs, SubExprs+END_EXPR); - } -private: - friend class ASTStmtReader; -}; - - -/// \brief An expression that sends a message to the given Objective-C -/// object or class. -/// -/// The following contains two message send expressions: -/// -/// \code -/// [[NSString alloc] initWithString:@"Hello"] -/// \endcode -/// -/// The innermost message send invokes the "alloc" class method on the -/// NSString class, while the outermost message send invokes the -/// "initWithString" instance method on the object returned from -/// NSString's "alloc". In all, an Objective-C message send can take -/// on four different (although related) forms: -/// -/// 1. Send to an object instance. -/// 2. Send to a class. -/// 3. Send to the superclass instance of the current class. -/// 4. Send to the superclass of the current class. -/// -/// All four kinds of message sends are modeled by the ObjCMessageExpr -/// class, and can be distinguished via \c getReceiverKind(). Example: -/// -/// The "void *" trailing objects are actually ONE void * (the -/// receiver pointer), and NumArgs Expr *. But due to the -/// implementation of children(), these must be together contiguously. - -class ObjCMessageExpr final - : public Expr, - private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { - /// \brief Stores either the selector that this message is sending - /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer - /// referring to the method that we type-checked against. - uintptr_t SelectorOrMethod; - - enum { NumArgsBitWidth = 16 }; - - /// \brief The number of arguments in the message send, not - /// including the receiver. - unsigned NumArgs : NumArgsBitWidth; - - /// \brief The kind of message send this is, which is one of the - /// ReceiverKind values. - /// - /// We pad this out to a byte to avoid excessive masking and shifting. - unsigned Kind : 8; - - /// \brief Whether we have an actual method prototype in \c - /// SelectorOrMethod. - /// - /// When non-zero, we have a method declaration; otherwise, we just - /// have a selector. - unsigned HasMethod : 1; - - /// \brief Whether this message send is a "delegate init call", - /// i.e. a call of an init method on self from within an init method. - unsigned IsDelegateInitCall : 1; - - /// \brief Whether this message send was implicitly generated by - /// the implementation rather than explicitly written by the user. - unsigned IsImplicit : 1; - - /// \brief Whether the locations of the selector identifiers are in a - /// "standard" position, a enum SelectorLocationsKind. - unsigned SelLocsKind : 2; - - /// \brief When the message expression is a send to 'super', this is - /// the location of the 'super' keyword. - SourceLocation SuperLoc; - - /// \brief The source locations of the open and close square - /// brackets ('[' and ']', respectively). - SourceLocation LBracLoc, RBracLoc; - - size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; } - - void setNumArgs(unsigned Num) { - assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!"); - NumArgs = Num; - } - - ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0), - HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) { - setNumArgs(NumArgs); - } - - ObjCMessageExpr(QualType T, ExprValueKind VK, - SourceLocation LBracLoc, - SourceLocation SuperLoc, - bool IsInstanceSuper, - QualType SuperType, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - ObjCMessageExpr(QualType T, ExprValueKind VK, - SourceLocation LBracLoc, - TypeSourceInfo *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - ObjCMessageExpr(QualType T, ExprValueKind VK, - SourceLocation LBracLoc, - Expr *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - - void initArgsAndSelLocs(ArrayRef<Expr *> Args, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK); - - /// \brief Retrieve the pointer value of the message receiver. - void *getReceiverPointer() const { return *getTrailingObjects<void *>(); } - - /// \brief Set the pointer value of the message receiver. - void setReceiverPointer(void *Value) { - *getTrailingObjects<void *>() = Value; - } - - SelectorLocationsKind getSelLocsKind() const { - return (SelectorLocationsKind)SelLocsKind; - } - bool hasStandardSelLocs() const { - return getSelLocsKind() != SelLoc_NonStandard; - } - - /// \brief Get a pointer to the stored selector identifiers locations array. - /// No locations will be stored if HasStandardSelLocs is true. - SourceLocation *getStoredSelLocs() { - return getTrailingObjects<SourceLocation>(); - } - const SourceLocation *getStoredSelLocs() const { - return getTrailingObjects<SourceLocation>(); - } - - /// \brief Get the number of stored selector identifiers locations. - /// No locations will be stored if HasStandardSelLocs is true. - unsigned getNumStoredSelLocs() const { - if (hasStandardSelLocs()) - return 0; - return getNumSelectorLocs(); - } - - static ObjCMessageExpr *alloc(const ASTContext &C, - ArrayRef<Expr *> Args, - SourceLocation RBraceLoc, - ArrayRef<SourceLocation> SelLocs, - Selector Sel, - SelectorLocationsKind &SelLocsK); - static ObjCMessageExpr *alloc(const ASTContext &C, - unsigned NumArgs, - unsigned NumStoredSelLocs); - -public: - /// \brief The kind of receiver this message is sending to. - enum ReceiverKind { - /// \brief The receiver is a class. - Class = 0, - /// \brief The receiver is an object instance. - Instance, - /// \brief The receiver is a superclass. - SuperClass, - /// \brief The receiver is the instance of the superclass object. - SuperInstance - }; - - /// \brief Create a message send to super. - /// - /// \param Context The ASTContext in which this expression will be created. - /// - /// \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 LBracLoc The location of the open square bracket '['. - /// - /// \param SuperLoc The location of the "super" keyword. - /// - /// \param IsInstanceSuper Whether this is an instance "super" - /// message (otherwise, it's a class "super" message). - /// - /// \param Sel The selector used to determine which method gets called. - /// - /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. - /// - /// \param Args The message send arguments. - /// - /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - SourceLocation SuperLoc, - bool IsInstanceSuper, - QualType SuperType, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - - /// \brief Create a class message send. - /// - /// \param Context The ASTContext in which this expression will be created. - /// - /// \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 LBracLoc The location of the open square bracket '['. - /// - /// \param Receiver The type of the receiver, including - /// source-location information. - /// - /// \param Sel The selector used to determine which method gets called. - /// - /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. - /// - /// \param Args The message send arguments. - /// - /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - TypeSourceInfo *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - - /// \brief Create an instance message send. - /// - /// \param Context The ASTContext in which this expression will be created. - /// - /// \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 LBracLoc The location of the open square bracket '['. - /// - /// \param Receiver The expression used to produce the object that - /// will receive this message. - /// - /// \param Sel The selector used to determine which method gets called. - /// - /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. - /// - /// \param Args The message send arguments. - /// - /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - Expr *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SeLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit); - - /// \brief Create an empty Objective-C message expression, to be - /// filled in by subsequent calls. - /// - /// \param Context The context in which the message send will be created. - /// - /// \param NumArgs The number of message arguments, not including - /// the receiver. - static ObjCMessageExpr *CreateEmpty(const ASTContext &Context, - unsigned NumArgs, - unsigned NumStoredSelLocs); - - /// \brief Indicates whether the message send was implicitly - /// generated by the implementation. If false, it was written explicitly - /// in the source code. - bool isImplicit() const { return IsImplicit; } - - /// \brief Determine the kind of receiver that this message is being - /// 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 { - return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; - } - - /// \brief Determine whether this is an class message to either a - /// specified class or to super. - bool isClassMessage() const { - return getReceiverKind() == Class || getReceiverKind() == SuperClass; - } - - /// \brief Returns the object expression (receiver) for an instance message, - /// or null for a message that is not an instance message. - Expr *getInstanceReceiver() { - if (getReceiverKind() == Instance) - return static_cast<Expr *>(getReceiverPointer()); - - return nullptr; - } - const Expr *getInstanceReceiver() const { - return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); - } - - /// \brief Turn this message send into an instance message that - /// computes the receiver object with the given expression. - void setInstanceReceiver(Expr *rec) { - Kind = Instance; - setReceiverPointer(rec); - } - - /// \brief Returns the type of a class message send, or NULL if the - /// message is not a class message. - QualType getClassReceiver() const { - if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) - return TSInfo->getType(); - - return QualType(); - } - - /// \brief Returns a type-source information of a class message - /// send, or NULL if the message is not a class message. - TypeSourceInfo *getClassReceiverTypeInfo() const { - if (getReceiverKind() == Class) - return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); - return nullptr; - } - - void setClassReceiver(TypeSourceInfo *TSInfo) { - Kind = Class; - setReceiverPointer(TSInfo); - } - - /// \brief Retrieve the location of the 'super' keyword for a class - /// or instance message to 'super', otherwise an invalid source location. - SourceLocation getSuperLoc() const { - if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) - return SuperLoc; - - return SourceLocation(); - } - - /// \brief Retrieve the receiver type to which this message is being directed. - /// - /// This routine cross-cuts all of the different kinds of message - /// sends to determine what the underlying (statically known) type - /// of the receiver will be; use \c getReceiverKind() to determine - /// whether the message is a class or an instance method, whether it - /// is a send to super or not, etc. - /// - /// \returns The type of the receiver. - QualType getReceiverType() const; - - /// \brief Retrieve the Objective-C interface to which this message - /// is being directed, if known. - /// - /// This routine cross-cuts all of the different kinds of message - /// sends to determine what the underlying (statically known) type - /// of the receiver will be; use \c getReceiverKind() to determine - /// whether the message is a class or an instance method, whether it - /// is a send to super or not, etc. - /// - /// \returns The Objective-C interface if known, otherwise NULL. - ObjCInterfaceDecl *getReceiverInterface() const; - - /// \brief Retrieve the type referred to by 'super'. - /// - /// The returned type will either be an ObjCInterfaceType (for an - /// class message to super) or an ObjCObjectPointerType that refers - /// to a class (for an instance message to super); - QualType getSuperType() const { - if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) - return QualType::getFromOpaquePtr(getReceiverPointer()); - - return QualType(); - } - - void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { - Kind = IsInstanceSuper? SuperInstance : SuperClass; - SuperLoc = Loc; - setReceiverPointer(T.getAsOpaquePtr()); - } - - Selector getSelector() const; - - void setSelector(Selector S) { - HasMethod = false; - SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); - } - - const ObjCMethodDecl *getMethodDecl() const { - if (HasMethod) - return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); - - return nullptr; - } - - ObjCMethodDecl *getMethodDecl() { - if (HasMethod) - return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); - - return nullptr; - } - - void setMethodDecl(ObjCMethodDecl *MD) { - HasMethod = true; - SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); - } - - ObjCMethodFamily getMethodFamily() const { - if (HasMethod) return getMethodDecl()->getMethodFamily(); - return getSelector().getMethodFamily(); - } - - /// \brief Return the number of actual arguments in this message, - /// not counting the receiver. - unsigned getNumArgs() const { return NumArgs; } - - /// \brief Retrieve the arguments to this message, not including the - /// receiver. - Expr **getArgs() { - return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1); - } - const Expr * const *getArgs() const { - return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() + - 1); - } - - /// getArg - Return the specified argument. - Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return getArgs()[Arg]; - } - const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return getArgs()[Arg]; - } - /// setArg - Set the specified argument. - void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); - getArgs()[Arg] = ArgExpr; - } - - /// isDelegateInitCall - Answers whether this message send has been - /// tagged as a "delegate init call", i.e. a call to a method in the - /// -init family on self from within an -init method implementation. - bool isDelegateInitCall() const { return IsDelegateInitCall; } - void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; } - - SourceLocation getLeftLoc() const { return LBracLoc; } - SourceLocation getRightLoc() const { return RBracLoc; } - - SourceLocation getSelectorStartLoc() const { - if (isImplicit()) - return getLocStart(); - return getSelectorLoc(0); - } - SourceLocation getSelectorLoc(unsigned Index) const { - assert(Index < getNumSelectorLocs() && "Index out of range!"); - if (hasStandardSelLocs()) - return getStandardSelectorLoc(Index, getSelector(), - getSelLocsKind() == SelLoc_StandardWithSpace, - llvm::makeArrayRef(const_cast<Expr**>(getArgs()), - getNumArgs()), - RBracLoc); - return getStoredSelLocs()[Index]; - } - - void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const; - - unsigned getNumSelectorLocs() const { - if (isImplicit()) - return 0; - Selector Sel = getSelector(); - if (Sel.isUnarySelector()) - return 1; - return Sel.getNumArgs(); - } - - void setSourceRange(SourceRange R) { - LBracLoc = R.getBegin(); - RBracLoc = R.getEnd(); - } - SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCMessageExprClass; - } - - // Iterators - child_range children(); - - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - - llvm::iterator_range<arg_iterator> arguments() { - return llvm::make_range(arg_begin(), arg_end()); - } - - llvm::iterator_range<const_arg_iterator> arguments() const { - return llvm::make_range(arg_begin(), arg_end()); - } - - 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); - } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. -/// (similar in spirit to MemberExpr). -class ObjCIsaExpr : public Expr { - /// Base - the expression for the base object pointer. - Stmt *Base; - - /// IsaMemberLoc - This is the location of the 'isa'. - SourceLocation IsaMemberLoc; - - /// OpLoc - This is the location of '.' or '->' - SourceLocation OpLoc; - - /// IsArrow - True if this is "X->F", false if this is "X.F". - bool IsArrow; -public: - ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, - QualType ty) - : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - /*ContainsUnexpandedParameterPack=*/false), - Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} - - /// \brief Build an empty expression. - explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } - - void setBase(Expr *E) { Base = E; } - Expr *getBase() const { return cast<Expr>(Base); } - - bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } - - /// getMemberLoc - Return the location of the "member", in X->F, it is the - /// location of 'F'. - SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } - void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } - - SourceLocation getOpLoc() const { return OpLoc; } - void setOpLoc(SourceLocation L) { OpLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); - } - - SourceLocation getBaseLocEnd() const LLVM_READONLY { - return getBase()->getLocEnd(); - } - - SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; } - - SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCIsaExprClass; - } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } -}; - - -/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function -/// argument by indirect copy-restore in ARC. This is used to support -/// passing indirect arguments with the wrong lifetime, e.g. when -/// passing the address of a __strong local variable to an 'out' -/// parameter. This expression kind is only valid in an "argument" -/// position to some sort of call expression. -/// -/// The parameter must have type 'pointer to T', and the argument must -/// have type 'pointer to U', where T and U agree except possibly in -/// qualification. If the argument value is null, then a null pointer -/// is passed; otherwise it points to an object A, and: -/// 1. A temporary object B of type T is initialized, either by -/// zero-initialization (used when initializing an 'out' parameter) -/// or copy-initialization (used when initializing an 'inout' -/// parameter). -/// 2. The address of the temporary is passed to the function. -/// 3. If the call completes normally, A is move-assigned from B. -/// 4. Finally, A is destroyed immediately. -/// -/// Currently 'T' must be a retainable object lifetime and must be -/// __autoreleasing; this qualifier is ignored when initializing -/// the value. -class ObjCIndirectCopyRestoreExpr : public Expr { - Stmt *Operand; - - // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1; - - friend class ASTReader; - friend class ASTStmtReader; - - void setShouldCopy(bool shouldCopy) { - ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy; - } - - explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) - : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { } - -public: - ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) - : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary, - operand->isTypeDependent(), operand->isValueDependent(), - operand->isInstantiationDependent(), - operand->containsUnexpandedParameterPack()), - Operand(operand) { - setShouldCopy(shouldCopy); - } - - Expr *getSubExpr() { return cast<Expr>(Operand); } - const Expr *getSubExpr() const { return cast<Expr>(Operand); } - - /// shouldCopy - True if we should do the 'copy' part of the - /// copy-restore. If false, the temporary will be zero-initialized. - bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; } - - child_range children() { return child_range(&Operand, &Operand+1); } - - // Source locations are determined by the subexpression. - SourceLocation getLocStart() const LLVM_READONLY { - return Operand->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();} - - SourceLocation getExprLoc() const LLVM_READONLY { - return getSubExpr()->getExprLoc(); - } - - static bool classof(const Stmt *s) { - return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; - } -}; - -/// \brief An Objective-C "bridged" cast expression, which casts between -/// Objective-C pointers and C pointers, transferring ownership in the process. -/// -/// \code -/// NSString *str = (__bridge_transfer NSString *)CFCreateString(); -/// \endcode -class ObjCBridgedCastExpr final - : public ExplicitCastExpr, - private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { - SourceLocation LParenLoc; - SourceLocation BridgeKeywordLoc; - unsigned Kind : 2; - - friend TrailingObjects; - friend class CastExpr; - friend class ASTStmtReader; - friend class ASTStmtWriter; - -public: - ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, - CastKind CK, SourceLocation BridgeKeywordLoc, - TypeSourceInfo *TSInfo, Expr *Operand) - : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, - CK, Operand, 0, TSInfo), - LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { } - - /// \brief Construct an empty Objective-C bridged cast. - explicit ObjCBridgedCastExpr(EmptyShell Shell) - : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { } - - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Determine which kind of bridge is being performed via this cast. - ObjCBridgeCastKind getBridgeKind() const { - return static_cast<ObjCBridgeCastKind>(Kind); - } - - /// \brief Retrieve the kind of bridge being performed as a string. - StringRef getBridgeKindName() const; - - /// \brief The location of the bridge keyword. - SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSubExpr()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCBridgedCastExprClass; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h deleted file mode 100644 index 2d71a3a..0000000 --- a/include/clang/AST/ExprOpenMP.h +++ /dev/null @@ -1,129 +0,0 @@ -//===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 Expr interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_EXPROPENMP_H -#define LLVM_CLANG_AST_EXPROPENMP_H - -#include "clang/AST/Expr.h" - -namespace clang { -/// \brief OpenMP 4.0 [2.4, Array Sections]. -/// To specify an array section in an OpenMP construct, array subscript -/// expressions are extended with the following syntax: -/// \code -/// [ lower-bound : length ] -/// [ lower-bound : ] -/// [ : length ] -/// [ : ] -/// \endcode -/// The array section must be a subset of the original array. -/// Array sections are allowed on multidimensional arrays. Base language array -/// subscript expressions can be used to specify length-one dimensions of -/// multidimensional array sections. -/// The lower-bound and length are integral type expressions. When evaluated -/// they represent a set of integer values as follows: -/// \code -/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length - -/// 1 } -/// \endcode -/// The lower-bound and length must evaluate to non-negative integers. -/// When the size of the array dimension is not known, the length must be -/// specified explicitly. -/// When the length is absent, it defaults to the size of the array dimension -/// minus the lower-bound. -/// When the lower-bound is absent it defaults to 0. -class OMPArraySectionExpr : public Expr { - enum { BASE, LOWER_BOUND, LENGTH, END_EXPR }; - Stmt *SubExprs[END_EXPR]; - SourceLocation ColonLoc; - SourceLocation RBracketLoc; - -public: - OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation ColonLoc, SourceLocation RBracketLoc) - : Expr( - OMPArraySectionExprClass, Type, VK, OK, - Base->isTypeDependent() || - (LowerBound && LowerBound->isTypeDependent()) || - (Length && Length->isTypeDependent()), - Base->isValueDependent() || - (LowerBound && LowerBound->isValueDependent()) || - (Length && Length->isValueDependent()), - Base->isInstantiationDependent() || - (LowerBound && LowerBound->isInstantiationDependent()) || - (Length && Length->isInstantiationDependent()), - Base->containsUnexpandedParameterPack() || - (LowerBound && LowerBound->containsUnexpandedParameterPack()) || - (Length && Length->containsUnexpandedParameterPack())), - ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) { - SubExprs[BASE] = Base; - SubExprs[LOWER_BOUND] = LowerBound; - SubExprs[LENGTH] = Length; - } - - /// \brief Create an empty array section expression. - explicit OMPArraySectionExpr(EmptyShell Shell) - : Expr(OMPArraySectionExprClass, Shell) {} - - /// An array section can be written only as Base[LowerBound:Length]. - - /// \brief Get base of the array section. - Expr *getBase() { return cast<Expr>(SubExprs[BASE]); } - const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); } - /// \brief Set base of the array section. - void setBase(Expr *E) { SubExprs[BASE] = E; } - - /// \brief Return original type of the base expression for array section. - static QualType getBaseOriginalType(Expr *Base); - - /// \brief Get lower bound of array section. - Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); } - const Expr *getLowerBound() const { - return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); - } - /// \brief Set lower bound of the array section. - void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; } - - /// \brief Get length of array section. - Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); } - const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); } - /// \brief Set length of the array section. - void setLength(Expr *E) { SubExprs[LENGTH] = E; } - - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } - - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } - - SourceLocation getRBracketLoc() const { return RBracketLoc; } - void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - - SourceLocation getExprLoc() const LLVM_READONLY { - return getBase()->getExprLoc(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPArraySectionExprClass; - } - - child_range children() { - return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]); - } -}; -} // end namespace clang - -#endif diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h deleted file mode 100644 index 81cf631..0000000 --- a/include/clang/AST/ExternalASTSource.h +++ /dev/null @@ -1,578 +0,0 @@ -//===--- ExternalASTSource.h - Abstract External AST 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 ExternalASTSource interface, which enables -// construction of AST nodes from some external source. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H -#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H - -#include "clang/AST/CharUnits.h" -#include "clang/AST/DeclBase.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { - -class ASTConsumer; -class CXXBaseSpecifier; -class CXXCtorInitializer; -class DeclarationName; -class ExternalSemaSource; // layering violation required for downcasting -class FieldDecl; -class Module; -class NamedDecl; -class RecordDecl; -class Selector; -class Stmt; -class TagDecl; - -/// \brief Abstract interface for external sources of AST nodes. -/// -/// External AST sources provide AST nodes constructed from some -/// external source, such as a precompiled header. External AST -/// sources can resolve types and declarations from abstract IDs into -/// actual type and declaration nodes, and read parts of declaration -/// contexts. -class ExternalASTSource : public RefCountedBase<ExternalASTSource> { - /// Generation number for this external AST source. Must be increased - /// whenever we might have added new redeclarations for existing decls. - uint32_t CurrentGeneration; - - /// \brief Whether this AST source also provides information for - /// semantic analysis. - bool SemaSource; - - friend class ExternalSemaSource; - -public: - ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { } - - virtual ~ExternalASTSource(); - - /// \brief RAII class for safely pairing a StartedDeserializing call - /// with FinishedDeserializing. - class Deserializing { - ExternalASTSource *Source; - public: - explicit Deserializing(ExternalASTSource *source) : Source(source) { - assert(Source); - Source->StartedDeserializing(); - } - ~Deserializing() { - Source->FinishedDeserializing(); - } - }; - - /// \brief Get the current generation of this AST source. This number - /// is incremented each time the AST source lazily extends an existing - /// entity. - uint32_t getGeneration() const { return CurrentGeneration; } - - /// \brief Resolve a declaration ID into a declaration, potentially - /// building a new declaration. - /// - /// This method only needs to be implemented if the AST source ever - /// passes back decl sets as VisibleDeclaration objects. - /// - /// The default implementation of this method is a no-op. - virtual Decl *GetExternalDecl(uint32_t ID); - - /// \brief Resolve a selector ID into a selector. - /// - /// This operation only needs to be implemented if the AST source - /// returns non-zero for GetNumKnownSelectors(). - /// - /// The default implementation of this method is a no-op. - virtual Selector GetExternalSelector(uint32_t ID); - - /// \brief Returns the number of selectors known to the external AST - /// source. - /// - /// The default implementation of this method is a no-op. - virtual uint32_t GetNumExternalSelectors(); - - /// \brief Resolve the offset of a statement in the decl stream into - /// a statement. - /// - /// This operation is meant to be used via a LazyOffsetPtr. It only - /// needs to be implemented if the AST source uses methods like - /// FunctionDecl::setLazyBody when building decls. - /// - /// The default implementation of this method is a no-op. - virtual Stmt *GetExternalDeclStmt(uint64_t Offset); - - /// \brief Resolve the offset of a set of C++ constructor initializers in - /// the decl stream into an array of initializers. - /// - /// The default implementation of this method is a no-op. - virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset); - - /// \brief Resolve the offset of a set of C++ base specifiers in the decl - /// stream into an array of specifiers. - /// - /// The default implementation of this method is a no-op. - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - - /// \brief Update an out-of-date identifier. - virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { } - - /// \brief Find all declarations with the given name in the given context, - /// and add them to the context by calling SetExternalVisibleDeclsForName - /// or SetNoExternalVisibleDeclsForName. - /// \return \c true if any declarations might have been found, \c false if - /// we definitely have no declarations with tbis name. - /// - /// The default implementation of this method is a no-op returning \c false. - virtual bool - FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); - - /// \brief Ensures that the table of all visible declarations inside this - /// context is up to date. - /// - /// The default implementation of this function is a no-op. - virtual void completeVisibleDeclsMap(const DeclContext *DC); - - /// \brief Retrieve the module that corresponds to the given module ID. - virtual Module *getModule(unsigned ID) { return nullptr; } - - /// Abstracts clang modules and precompiled header files and holds - /// everything needed to generate debug info for an imported module - /// or PCH. - class ASTSourceDescriptor { - StringRef PCHModuleName; - StringRef Path; - StringRef ASTFile; - uint64_t Signature = 0; - const Module *ClangModule = nullptr; - - public: - ASTSourceDescriptor(){}; - ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, - uint64_t Signature) - : PCHModuleName(std::move(Name)), Path(std::move(Path)), - ASTFile(std::move(ASTFile)), Signature(Signature){}; - ASTSourceDescriptor(const Module &M); - std::string getModuleName() const; - StringRef getPath() const { return Path; } - StringRef getASTFile() const { return ASTFile; } - uint64_t getSignature() const { return Signature; } - const Module *getModuleOrNull() const { return ClangModule; } - }; - - /// Return a descriptor for the corresponding module, if one exists. - virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); - - /// \brief Finds all declarations lexically contained within the given - /// 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. - /// - /// The default implementation of this method is a no-op. - virtual void - FindExternalLexicalDecls(const DeclContext *DC, - llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, - SmallVectorImpl<Decl *> &Result); - - /// \brief Finds all declarations lexically contained within the given - /// DeclContext. - void FindExternalLexicalDecls(const DeclContext *DC, - SmallVectorImpl<Decl *> &Result) { - FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result); - } - - /// \brief Get the decls that are contained in a file in the Offset/Length - /// range. \p Length can be 0 to indicate a point at \p Offset instead of - /// a range. - virtual void FindFileRegionDecls(FileID File, unsigned Offset, - unsigned Length, - SmallVectorImpl<Decl *> &Decls); - - /// \brief Gives the external AST source an opportunity to complete - /// the redeclaration chain for a declaration. Called each time we - /// need the most recent declaration of a declaration after the - /// generation count is incremented. - virtual void CompleteRedeclChain(const Decl *D); - - /// \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 Loads comment ranges. - virtual void ReadComments(); - - /// \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. - /// - /// The default implementation of this method is a no-op. - virtual void StartedDeserializing(); - - /// \brief Notify ExternalASTSource that we finished the deserialization of - /// a decl or type. Must be paired with StartedDeserializing. - /// - /// The default implementation of this method is a no-op. - virtual void FinishedDeserializing(); - - /// \brief Function that will be invoked when we begin parsing a new - /// translation unit involving this external AST source. - /// - /// The default implementation of this method is a no-op. - virtual void StartTranslationUnit(ASTConsumer *Consumer); - - /// \brief Print any statistics that have been gathered regarding - /// the external AST source. - /// - /// The default implementation of this method is a no-op. - virtual void PrintStats(); - - - /// \brief Perform layout on the given record. - /// - /// This routine allows the external AST source to provide an specific - /// layout for a record, overriding the layout that would normally be - /// constructed. It is intended for clients who receive specific layout - /// details rather than source code (such as LLDB). The client is expected - /// to fill in the field offsets, base offsets, virtual base offsets, and - /// complete object size. - /// - /// \param Record The record whose layout is being requested. - /// - /// \param Size The final size of the record, in bits. - /// - /// \param Alignment The final alignment of the record, in bits. - /// - /// \param FieldOffsets The offset of each of the fields within the record, - /// expressed in bits. All of the fields must be provided with offsets. - /// - /// \param BaseOffsets The offset of each of the direct, non-virtual base - /// classes. If any bases are not given offsets, the bases will be laid - /// out according to the ABI. - /// - /// \param VirtualBaseOffsets The offset of each of the virtual base classes - /// (either direct or not). If any bases are not given offsets, the bases will be laid - /// out according to the ABI. - /// - /// \returns true if the record layout was provided, false otherwise. - virtual bool layoutRecordType( - const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); - - //===--------------------------------------------------------------------===// - // Queries for performance analysis. - //===--------------------------------------------------------------------===// - - struct MemoryBufferSizes { - size_t malloc_bytes; - size_t mmap_bytes; - - MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) - : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} - }; - - /// Return the amount of memory used by memory buffers, breaking down - /// by heap-backed versus mmap'ed memory. - MemoryBufferSizes getMemoryBufferSizes() const { - MemoryBufferSizes sizes(0, 0); - getMemoryBufferSizes(sizes); - return sizes; - } - - virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; - -protected: - static DeclContextLookupResult - SetExternalVisibleDeclsForName(const DeclContext *DC, - DeclarationName Name, - ArrayRef<NamedDecl*> Decls); - - static DeclContextLookupResult - SetNoExternalVisibleDeclsForName(const DeclContext *DC, - DeclarationName Name); - - /// \brief Increment the current generation. - uint32_t incrementGeneration(ASTContext &C); -}; - -/// \brief A lazy pointer to an AST node (of base type T) that resides -/// within an external AST source. -/// -/// The AST node is identified within the external AST source by a -/// 63-bit offset, and can be retrieved via an operation on the -/// external AST source itself. -template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> -struct LazyOffsetPtr { - /// \brief Either a pointer to an AST node or the offset within the - /// external AST source where the AST node can be found. - /// - /// If the low bit is clear, a pointer to the AST node. If the low - /// bit is set, the upper 63 bits are the offset. - mutable uint64_t Ptr; - -public: - LazyOffsetPtr() : Ptr(0) { } - - explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } - explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { - assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); - if (Offset == 0) - Ptr = 0; - } - - LazyOffsetPtr &operator=(T *Ptr) { - this->Ptr = reinterpret_cast<uint64_t>(Ptr); - return *this; - } - - LazyOffsetPtr &operator=(uint64_t Offset) { - assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); - if (Offset == 0) - Ptr = 0; - else - Ptr = (Offset << 1) | 0x01; - - return *this; - } - - /// \brief Whether this pointer is non-NULL. - /// - /// This operation does not require the AST node to be deserialized. - explicit operator bool() const { return Ptr != 0; } - - /// \brief Whether this pointer is non-NULL. - /// - /// This operation does not require the AST node to be deserialized. - bool isValid() const { return Ptr != 0; } - - /// \brief Whether this pointer is currently stored as an offset. - bool isOffset() const { return Ptr & 0x01; } - - /// \brief Retrieve the pointer to the AST node that this lazy pointer - /// - /// \param Source the external AST source. - /// - /// \returns a pointer to the AST node. - T* get(ExternalASTSource *Source) const { - if (isOffset()) { - assert(Source && - "Cannot deserialize a lazy pointer without an AST source"); - Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); - } - return reinterpret_cast<T*>(Ptr); - } -}; - -/// \brief A lazy value (of type T) that is within an AST node of type Owner, -/// where the value might change in later generations of the external AST -/// source. -template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> -struct LazyGenerationalUpdatePtr { - /// A cache of the value of this pointer, in the most recent generation in - /// which we queried it. - struct LazyData { - LazyData(ExternalASTSource *Source, T Value) - : ExternalSource(Source), LastGeneration(0), LastValue(Value) {} - ExternalASTSource *ExternalSource; - uint32_t LastGeneration; - T LastValue; - }; - - // Our value is represented as simply T if there is no external AST source. - typedef llvm::PointerUnion<T, LazyData*> ValueType; - ValueType Value; - - LazyGenerationalUpdatePtr(ValueType V) : Value(V) {} - - // Defined in ASTContext.h - static ValueType makeValue(const ASTContext &Ctx, T Value); - -public: - explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T()) - : Value(makeValue(Ctx, Value)) {} - - /// Create a pointer that is not potentially updated by later generations of - /// the external AST source. - enum NotUpdatedTag { NotUpdated }; - LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T()) - : Value(Value) {} - - /// Forcibly set this pointer (which must be lazy) as needing updates. - void markIncomplete() { - Value.template get<LazyData *>()->LastGeneration = 0; - } - - /// Set the value of this pointer, in the current generation. - void set(T NewValue) { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { - LazyVal->LastValue = NewValue; - return; - } - Value = NewValue; - } - - /// Set the value of this pointer, for this and all future generations. - void setNotUpdated(T NewValue) { Value = NewValue; } - - /// Get the value of this pointer, updating its owner if necessary. - T get(Owner O) { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { - if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { - LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); - (LazyVal->ExternalSource->*Update)(O); - } - return LazyVal->LastValue; - } - return Value.template get<T>(); - } - - /// Get the most recently computed value of this pointer without updating it. - T getNotUpdated() const { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) - return LazyVal->LastValue; - return Value.template get<T>(); - } - - void *getOpaqueValue() { return Value.getOpaqueValue(); } - static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) { - return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr)); - } -}; -} // end namespace clang - -/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be -/// placed into a PointerUnion. -namespace llvm { -template<typename Owner, typename T, - void (clang::ExternalASTSource::*Update)(Owner)> -struct PointerLikeTypeTraits< - clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { - typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr; - static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } - static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } - enum { - NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 - }; -}; -} - -namespace clang { -/// \brief Represents a lazily-loaded vector of data. -/// -/// The lazily-loaded vector of data contains data that is partially loaded -/// from an external source and partially added by local translation. The -/// items loaded from the external source are loaded lazily, when needed for -/// iteration over the complete vector. -template<typename T, typename Source, - void (Source::*Loader)(SmallVectorImpl<T>&), - unsigned LoadedStorage = 2, unsigned LocalStorage = 4> -class LazyVector { - SmallVector<T, LoadedStorage> Loaded; - SmallVector<T, LocalStorage> Local; - -public: - /// Iteration over the elements in the vector. - /// - /// In a complete iteration, the iterator walks the range [-M, N), - /// where negative values are used to indicate elements - /// loaded from the external source while non-negative values are used to - /// indicate elements added via \c push_back(). - /// However, to provide iteration in source order (for, e.g., chained - /// precompiled headers), dereferencing the iterator flips the negative - /// values (corresponding to loaded entities), so that position -M - /// corresponds to element 0 in the loaded entities vector, position -M+1 - /// corresponds to element 1 in the loaded entities vector, etc. This - /// gives us a reasonably efficient, source-order walk. - /// - /// We define this as a wrapping iterator around an int. The - /// iterator_adaptor_base class forwards the iterator methods to basic integer - /// arithmetic. - class iterator : public llvm::iterator_adaptor_base< - iterator, int, std::random_access_iterator_tag, T, int> { - LazyVector *Self; - - iterator(LazyVector *Self, int Position) - : iterator::iterator_adaptor_base(Position), Self(Self) {} - - bool isLoaded() const { return this->I < 0; } - friend class LazyVector; - - public: - iterator() : iterator(nullptr, 0) {} - - typename iterator::reference operator*() const { - if (isLoaded()) - return Self->Loaded.end()[this->I]; - return Self->Local.begin()[this->I]; - } - }; - - iterator begin(Source *source, bool LocalOnly = false) { - if (LocalOnly) - return iterator(this, 0); - - if (source) - (source->*Loader)(Loaded); - return iterator(this, -(int)Loaded.size()); - } - - iterator end() { - return iterator(this, Local.size()); - } - - void push_back(const T& LocalValue) { - Local.push_back(LocalValue); - } - - void erase(iterator From, iterator To) { - if (From.isLoaded() && To.isLoaded()) { - Loaded.erase(&*From, &*To); - return; - } - - if (From.isLoaded()) { - Loaded.erase(&*From, Loaded.end()); - From = begin(nullptr, true); - } - - Local.erase(&*From, &*To); - } -}; - -/// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> - LazyDeclStmtPtr; - -/// \brief A lazy pointer to a declaration. -typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> - LazyDeclPtr; - -/// \brief A lazy pointer to a set of CXXCtorInitializers. -typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t, - &ExternalASTSource::GetExternalCXXCtorInitializers> - LazyCXXCtorInitializersPtr; - -/// \brief A lazy pointer to a set of CXXBaseSpecifiers. -typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, - &ExternalASTSource::GetExternalCXXBaseSpecifiers> - LazyCXXBaseSpecifiersPtr; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h deleted file mode 100644 index 54c9d88..0000000 --- a/include/clang/AST/GlobalDecl.h +++ /dev/null @@ -1,125 +0,0 @@ -//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor -// together with its type. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_GLOBALDECL_H -#define LLVM_CLANG_AST_GLOBALDECL_H - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Basic/ABI.h" - -namespace clang { - -/// GlobalDecl - represents a global declaration. This can either be a -/// CXXConstructorDecl and the constructor type (Base, Complete). -/// a CXXDestructorDecl and the destructor type (Base, Complete) or -/// a VarDecl, a FunctionDecl or a BlockDecl. -class GlobalDecl { - llvm::PointerIntPair<const Decl*, 2> Value; - - void Init(const Decl *D) { - assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); - assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); - - Value.setPointer(D); - } - -public: - GlobalDecl() {} - - GlobalDecl(const VarDecl *D) { Init(D);} - GlobalDecl(const FunctionDecl *D) { Init(D); } - GlobalDecl(const BlockDecl *D) { Init(D); } - GlobalDecl(const CapturedDecl *D) { Init(D); } - GlobalDecl(const ObjCMethodDecl *D) { Init(D); } - - GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) - : Value(D, Type) {} - GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) - : Value(D, Type) {} - - GlobalDecl getCanonicalDecl() const { - GlobalDecl CanonGD; - CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); - CanonGD.Value.setInt(Value.getInt()); - - return CanonGD; - } - - const Decl *getDecl() const { return Value.getPointer(); } - - CXXCtorType getCtorType() const { - assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); - return static_cast<CXXCtorType>(Value.getInt()); - } - - CXXDtorType getDtorType() const { - assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); - return static_cast<CXXDtorType>(Value.getInt()); - } - - friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { - return LHS.Value == RHS.Value; - } - - void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } - - static GlobalDecl getFromOpaquePtr(void *P) { - GlobalDecl GD; - GD.Value.setFromOpaqueValue(P); - return GD; - } - - GlobalDecl getWithDecl(const Decl *D) { - GlobalDecl Result(*this); - Result.Value.setPointer(D); - return Result; - } -}; - -} // end namespace clang - -namespace llvm { - template<class> struct DenseMapInfo; - - template<> struct DenseMapInfo<clang::GlobalDecl> { - static inline clang::GlobalDecl getEmptyKey() { - return clang::GlobalDecl(); - } - - static inline clang::GlobalDecl getTombstoneKey() { - return clang::GlobalDecl:: - getFromOpaquePtr(reinterpret_cast<void*>(-1)); - } - - static unsigned getHashValue(clang::GlobalDecl GD) { - return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); - } - - static bool isEqual(clang::GlobalDecl LHS, - clang::GlobalDecl RHS) { - return LHS == RHS; - } - - }; - - // GlobalDecl isn't *technically* a POD type. However, its copy constructor, - // copy assignment operator, and destructor are all trivial. - template <> - struct isPodLike<clang::GlobalDecl> { - static const bool value = true; - }; -} // end namespace llvm - -#endif diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h deleted file mode 100644 index ddefa88..0000000 --- a/include/clang/AST/LambdaCapture.h +++ /dev/null @@ -1,128 +0,0 @@ -//===--- LambdaCapture.h - Types for C++ Lambda Captures --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the LambdaCapture class. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_LAMBDACAPTURE_H -#define LLVM_CLANG_AST_LAMBDACAPTURE_H - -#include "clang/AST/Decl.h" -#include "clang/Basic/Lambda.h" -#include "llvm/ADT/PointerIntPair.h" - -namespace clang { - -/// \brief Describes the capture of a variable or of \c this, or of a -/// C++1y init-capture. -class LambdaCapture { - enum { - /// \brief Flag used by the Capture class to indicate that the given - /// capture was implicit. - Capture_Implicit = 0x01, - - /// \brief Flag used by the Capture class to indicate that the - /// given capture was by-copy. - /// - /// This includes the case of a non-reference init-capture. - Capture_ByCopy = 0x02 - }; - - llvm::PointerIntPair<Decl *, 2> DeclAndBits; - SourceLocation Loc; - SourceLocation EllipsisLoc; - - friend class ASTStmtReader; - friend class ASTStmtWriter; - -public: - /// \brief Create a new capture of a variable or of \c this. - /// - /// \param Loc The source location associated with this capture. - /// - /// \param Kind The kind of capture (this, byref, bycopy), which must - /// not be init-capture. - /// - /// \param Implicit Whether the capture was implicit or explicit. - /// - /// \param Var The local variable being captured, or null if capturing - /// \c this. - /// - /// \param EllipsisLoc The location of the ellipsis (...) for a - /// capture that is a pack expansion, or an invalid source - /// location to indicate that this is not a pack expansion. - LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, - VarDecl *Var = nullptr, - SourceLocation EllipsisLoc = SourceLocation()); - - /// \brief Determine the kind of capture. - LambdaCaptureKind getCaptureKind() const; - - /// \brief Determine whether this capture handles the C++ \c this - /// pointer. - bool capturesThis() const { - return (DeclAndBits.getPointer() == nullptr) && - !(DeclAndBits.getInt() & Capture_ByCopy); - } - - /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { - return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this captures a variable length array bound - /// expression. - bool capturesVLAType() const { - return (DeclAndBits.getPointer() == nullptr) && - (DeclAndBits.getInt() & Capture_ByCopy); - } - - /// \brief Retrieve the declaration of the local variable being - /// captured. - /// - /// This operation is only valid if this capture is a variable capture - /// (other than a capture of \c this). - VarDecl *getCapturedVar() const { - assert(capturesVariable() && "No variable available for 'this' capture"); - return cast<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this was an implicit capture (not - /// written between the square brackets introducing the lambda). - bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } - - /// \brief Determine whether this was an explicit capture (written - /// between the square brackets introducing the lambda). - bool isExplicit() const { return !isImplicit(); } - - /// \brief Retrieve the source location of the capture. - /// - /// For an explicit capture, this returns the location of the - /// explicit capture in the source. For an implicit capture, this - /// returns the location at which the variable or \c this was first - /// used. - SourceLocation getLocation() const { return Loc; } - - /// \brief Determine whether this capture is a pack expansion, - /// which captures a function parameter pack. - bool isPackExpansion() const { return EllipsisLoc.isValid(); } - - /// \brief Retrieve the location of the ellipsis for a capture - /// that is a pack expansion. - SourceLocation getEllipsisLoc() const { - assert(isPackExpansion() && "No ellipsis location for a non-expansion"); - return EllipsisLoc; - } -}; - -} // end namespace clang - -#endif // LLVM_CLANG_AST_LAMBDACAPTURE_H diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile deleted file mode 100644 index 85e6449..0000000 --- a/include/clang/AST/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -CLANG_LEVEL := ../../.. -TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc AttrVisitor.inc \ - StmtNodes.inc DeclNodes.inc \ - CommentNodes.inc CommentHTMLTags.inc \ - CommentHTMLTagsProperties.inc \ - CommentHTMLNamedCharacterReferences.inc \ - CommentCommandInfo.inc \ - CommentCommandList.inc - -TABLEGEN_INC_FILES_COMMON = 1 - -include $(CLANG_LEVEL)/Makefile - -$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute classes with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute implementations with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrDump.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute dumper with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-dump -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrVisitor.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute AST visitor with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-ast-visitor -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang statement node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang declaration node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentNodes.inc.tmp : $(TD_SRC_DIR)/CommentNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang comment node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLTags.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang comment HTML tag matchers with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLTagsProperties.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang comment HTML tag properties with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLNamedCharacterReferences.inc.tmp : \ - $(PROJ_SRC_DIR)/CommentHTMLNamedCharacterReferences.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang named character reference translation function with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-named-character-references -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang comment command info with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentCommandList.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang list of comment commands with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-command-list -o $(call SYSPATH, $@) $< - diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h deleted file mode 100644 index 4872738..0000000 --- a/include/clang/AST/Mangle.h +++ /dev/null @@ -1,243 +0,0 @@ -//===--- 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/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.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 StringLiteral; - struct ThisAdjustment; - struct ThunkInfo; - class VarDecl; - -/// MangleContext - Context for tracking state which persists across multiple -/// calls to the C++ name mangler. -class MangleContext { -public: - enum ManglerKind { - MK_Itanium, - MK_Microsoft - }; - -private: - virtual void anchor(); - - ASTContext &Context; - DiagnosticsEngine &Diags; - const ManglerKind Kind; - - llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; - llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; - llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds; - -public: - ManglerKind getKind() const { return Kind; } - - explicit MangleContext(ASTContext &Context, - DiagnosticsEngine &Diags, - ManglerKind Kind) - : Context(Context), Diags(Diags), Kind(Kind) {} - - virtual ~MangleContext() { } - - ASTContext &getASTContext() const { return Context; } - - DiagnosticsEngine &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; - } - - uint64_t getAnonymousStructId(const TagDecl *TD) { - std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool> - Result = AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); - return Result.first->second; - } - - /// @name Mangler Entry Points - /// @{ - - bool shouldMangleDeclName(const NamedDecl *D); - virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; - virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; - - // FIXME: consider replacing raw_ostream & with something like SmallString &. - void mangleName(const NamedDecl *D, raw_ostream &); - virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0; - virtual void mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - raw_ostream &) = 0; - virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, - raw_ostream &) = 0; - virtual void mangleReferenceTemporary(const VarDecl *D, - unsigned ManglingNumber, - raw_ostream &) = 0; - virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; - virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; - virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &) = 0; - virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &) = 0; - virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; - - void mangleGlobalBlock(const BlockDecl *BD, - const NamedDecl *ID, - raw_ostream &Out); - void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, - const BlockDecl *BD, raw_ostream &Out); - void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, - const BlockDecl *BD, raw_ostream &Out); - void mangleBlock(const DeclContext *DC, const BlockDecl *BD, - raw_ostream &Out); - - void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &); - - virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0; - - virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0; - - virtual void mangleDynamicAtExitDestructor(const VarDecl *D, - raw_ostream &) = 0; - - virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl, - raw_ostream &Out) = 0; - - virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, - raw_ostream &Out) = 0; - - /// Generates a unique string for an externally visible type for use with TBAA - /// or type uniquing. - /// TODO: Extend this to internal types by generating names that are unique - /// across translation units so it can be used with LTO. - virtual void mangleTypeName(QualType T, raw_ostream &) = 0; - - /// @} -}; - -class ItaniumMangleContext : public MangleContext { -public: - explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) - : MangleContext(C, D, MK_Itanium) {} - - virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0; - virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0; - virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, - const CXXRecordDecl *Type, - raw_ostream &) = 0; - virtual void mangleItaniumThreadLocalInit(const VarDecl *D, - raw_ostream &) = 0; - virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, - raw_ostream &) = 0; - - virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, - raw_ostream &) = 0; - virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, - raw_ostream &) = 0; - - static bool classof(const MangleContext *C) { - return C->getKind() == MK_Itanium; - } - - static ItaniumMangleContext *create(ASTContext &Context, - DiagnosticsEngine &Diags); -}; - -class MicrosoftMangleContext : public MangleContext { -public: - explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D) - : MangleContext(C, D, MK_Microsoft) {} - - /// \brief Mangle vftable symbols. Only a subset of the bases along the path - /// to the vftable are included in the name. It's up to the caller to pick - /// them correctly. - virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out) = 0; - - /// \brief Mangle vbtable symbols. Only a subset of the bases along the path - /// to the vbtable are included in the name. It's up to the caller to pick - /// them correctly. - virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out) = 0; - - virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD, - unsigned GuardNum, - raw_ostream &Out) = 0; - - virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - raw_ostream &) = 0; - - virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD, - const CXXRecordDecl *DstRD, - raw_ostream &Out) = 0; - - virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, - uint32_t NumEntries, raw_ostream &Out) = 0; - - virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, - raw_ostream &Out) = 0; - - virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, - CXXCtorType CT, uint32_t Size, - uint32_t NVOffset, int32_t VBPtrOffset, - uint32_t VBIndex, raw_ostream &Out) = 0; - - virtual void mangleCXXRTTIBaseClassDescriptor( - const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, - uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0; - - virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived, - raw_ostream &Out) = 0; - virtual void - mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived, - raw_ostream &Out) = 0; - - virtual void - mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out) = 0; - - static bool classof(const MangleContext *C) { - return C->getKind() == MK_Microsoft; - } - - static MicrosoftMangleContext *create(ASTContext &Context, - DiagnosticsEngine &Diags); -}; -} - -#endif diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h deleted file mode 100644 index 7a81855..0000000 --- a/include/clang/AST/MangleNumberingContext.h +++ /dev/null @@ -1,60 +0,0 @@ -//=== MangleNumberingContext.h - Context for mangling numbers ---*- 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 LambdaBlockMangleContext interface, which keeps track -// of the Itanium C++ ABI mangling numbers for lambda expressions and block -// literals. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H -#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" - -namespace clang { - -class BlockDecl; -class CXXMethodDecl; -class IdentifierInfo; -class TagDecl; -class Type; -class VarDecl; - -/// \brief Keeps track of the mangled names of lambda expressions and block -/// literals within a particular context. -class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> { -public: - virtual ~MangleNumberingContext() {} - - /// \brief Retrieve the mangling number of a new lambda expression with the - /// given call operator within this context. - virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0; - - /// \brief Retrieve the mangling number of a new block literal within this - /// context. - virtual unsigned getManglingNumber(const BlockDecl *BD) = 0; - - /// Static locals are numbered by source order. - virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0; - - /// \brief Retrieve the mangling number of a static local variable within - /// this context. - virtual unsigned getManglingNumber(const VarDecl *VD, - unsigned MSLocalManglingNumber) = 0; - - /// \brief Retrieve the mangling number of a static local variable within - /// this context. - virtual unsigned getManglingNumber(const TagDecl *TD, - unsigned MSLocalManglingNumber) = 0; -}; - -} // end namespace clang -#endif diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h deleted file mode 100644 index 583f9d9..0000000 --- a/include/clang/AST/NSAPI.h +++ /dev/null @@ -1,262 +0,0 @@ -//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_NSAPI_H -#define LLVM_CLANG_AST_NSAPI_H - -#include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" - -namespace clang { - class ASTContext; - class ObjCInterfaceDecl; - class QualType; - class Expr; - -// \brief Provides info and caches identifiers/selectors for NSFoundation API. -class NSAPI { -public: - explicit NSAPI(ASTContext &Ctx); - - ASTContext &getASTContext() const { return Ctx; } - - enum NSClassIdKindKind { - ClassId_NSObject, - ClassId_NSString, - ClassId_NSArray, - ClassId_NSMutableArray, - ClassId_NSDictionary, - ClassId_NSMutableDictionary, - ClassId_NSNumber, - ClassId_NSMutableSet, - ClassId_NSMutableOrderedSet, - ClassId_NSValue - }; - static const unsigned NumClassIds = 10; - - enum NSStringMethodKind { - NSStr_stringWithString, - NSStr_stringWithUTF8String, - NSStr_stringWithCStringEncoding, - NSStr_stringWithCString, - NSStr_initWithString, - NSStr_initWithUTF8String - }; - static const unsigned NumNSStringMethods = 5; - - IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; - - /// \brief The Objective-C NSString selectors. - Selector getNSStringSelector(NSStringMethodKind MK) const; - - /// \brief Return NSStringMethodKind if \param Sel is such a selector. - Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; - - /// \brief Returns true if the expression \param E is a reference of - /// "NSUTF8StringEncoding" enum constant. - bool isNSUTF8StringEncodingConstant(const Expr *E) const { - return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId); - } - - /// \brief Returns true if the expression \param E is a reference of - /// "NSASCIIStringEncoding" enum constant. - bool isNSASCIIStringEncodingConstant(const Expr *E) const { - return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId); - } - - /// \brief Enumerates the NSArray/NSMutableArray methods used to generate - /// literals and to apply some checks. - enum NSArrayMethodKind { - NSArr_array, - NSArr_arrayWithArray, - NSArr_arrayWithObject, - NSArr_arrayWithObjects, - NSArr_arrayWithObjectsCount, - NSArr_initWithArray, - NSArr_initWithObjects, - NSArr_objectAtIndex, - NSMutableArr_replaceObjectAtIndex, - NSMutableArr_addObject, - NSMutableArr_insertObjectAtIndex, - NSMutableArr_setObjectAtIndexedSubscript - }; - static const unsigned NumNSArrayMethods = 12; - - /// \brief The Objective-C NSArray selectors. - Selector getNSArraySelector(NSArrayMethodKind MK) const; - - /// \brief Return NSArrayMethodKind if \p Sel is such a selector. - Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); - - /// \brief Enumerates the NSDictionary/NSMutableDictionary methods used - /// to generate literals and to apply some checks. - enum NSDictionaryMethodKind { - NSDict_dictionary, - NSDict_dictionaryWithDictionary, - NSDict_dictionaryWithObjectForKey, - NSDict_dictionaryWithObjectsForKeys, - NSDict_dictionaryWithObjectsForKeysCount, - NSDict_dictionaryWithObjectsAndKeys, - NSDict_initWithDictionary, - NSDict_initWithObjectsAndKeys, - NSDict_initWithObjectsForKeys, - NSDict_objectForKey, - NSMutableDict_setObjectForKey, - NSMutableDict_setObjectForKeyedSubscript, - NSMutableDict_setValueForKey - }; - static const unsigned NumNSDictionaryMethods = 14; - - /// \brief The Objective-C NSDictionary selectors. - Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; - - /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector. - Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); - - /// \brief Enumerates the NSMutableSet/NSOrderedSet methods used - /// to apply some checks. - enum NSSetMethodKind { - NSMutableSet_addObject, - NSOrderedSet_insertObjectAtIndex, - NSOrderedSet_setObjectAtIndex, - NSOrderedSet_setObjectAtIndexedSubscript, - NSOrderedSet_replaceObjectAtIndexWithObject - }; - static const unsigned NumNSSetMethods = 5; - - /// \brief The Objective-C NSSet selectors. - Selector getNSSetSelector(NSSetMethodKind MK) const; - - /// \brief Return NSSetMethodKind if \p Sel is such a selector. - Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel); - - /// \brief Returns selector for "objectForKeyedSubscript:". - Selector getObjectForKeyedSubscriptSelector() const { - return getOrInitSelector(StringRef("objectForKeyedSubscript"), - objectForKeyedSubscriptSel); - } - - /// \brief Returns selector for "objectAtIndexedSubscript:". - Selector getObjectAtIndexedSubscriptSelector() const { - return getOrInitSelector(StringRef("objectAtIndexedSubscript"), - objectAtIndexedSubscriptSel); - } - - /// \brief Returns selector for "setObject:forKeyedSubscript". - Selector getSetObjectForKeyedSubscriptSelector() const { - StringRef Ids[] = { "setObject", "forKeyedSubscript" }; - return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel); - } - - /// \brief Returns selector for "setObject:atIndexedSubscript". - Selector getSetObjectAtIndexedSubscriptSelector() const { - StringRef Ids[] = { "setObject", "atIndexedSubscript" }; - return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel); - } - - /// \brief Returns selector for "isEqual:". - Selector getIsEqualSelector() const { - return getOrInitSelector(StringRef("isEqual"), isEqualSel); - } - - /// \brief Enumerates the NSNumber methods used to generate literals. - enum NSNumberLiteralMethodKind { - NSNumberWithChar, - NSNumberWithUnsignedChar, - NSNumberWithShort, - NSNumberWithUnsignedShort, - NSNumberWithInt, - NSNumberWithUnsignedInt, - NSNumberWithLong, - NSNumberWithUnsignedLong, - NSNumberWithLongLong, - NSNumberWithUnsignedLongLong, - NSNumberWithFloat, - NSNumberWithDouble, - NSNumberWithBool, - NSNumberWithInteger, - NSNumberWithUnsignedInteger - }; - static const unsigned NumNSNumberLiteralMethods = 15; - - /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. - /// \param Instance if true it will return the selector for the init* method - /// otherwise it will return the selector for the number* method. - Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, - bool Instance) const; - - bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, - Selector Sel) const { - return Sel == getNSNumberLiteralSelector(MK, false) || - Sel == getNSNumberLiteralSelector(MK, true); - } - - /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector. - Optional<NSNumberLiteralMethodKind> - getNSNumberLiteralMethodKind(Selector Sel) const; - - /// \brief Determine the appropriate NSNumber factory method kind for a - /// literal of the given type. - Optional<NSNumberLiteralMethodKind> - getNSNumberFactoryMethodKind(QualType T) const; - - /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. - bool isObjCBOOLType(QualType T) const; - /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. - bool isObjCNSIntegerType(QualType T) const; - /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. - bool isObjCNSUIntegerType(QualType T) const; - /// \brief Returns one of NSIntegral typedef names if \param T is a typedef - /// of that name in objective-c. - StringRef GetNSIntegralKind(QualType T) const; - - /// \brief Returns \c true if \p Id is currently defined as a macro. - bool isMacroDefined(StringRef Id) const; - - /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind - bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl, - NSClassIdKindKind NSClassKind) const; - -private: - bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; - bool isObjCEnumerator(const Expr *E, - StringRef name, IdentifierInfo *&II) const; - Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const; - - ASTContext &Ctx; - - mutable IdentifierInfo *ClassIds[NumClassIds]; - - mutable Selector NSStringSelectors[NumNSStringMethods]; - - /// \brief The selectors for Objective-C NSArray methods. - mutable Selector NSArraySelectors[NumNSArrayMethods]; - - /// \brief The selectors for Objective-C NSDictionary methods. - mutable Selector NSDictionarySelectors[NumNSDictionaryMethods]; - - /// \brief The selectors for Objective-C NSSet methods. - mutable Selector NSSetSelectors[NumNSSetMethods]; - - /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. - mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods]; - mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; - - mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel, - setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel, - isEqualSel; - - mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId; - mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId; -}; - -} // end namespace clang - -#endif // LLVM_CLANG_AST_NSAPI_H diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h deleted file mode 100644 index b1ff9bd..0000000 --- a/include/clang/AST/NestedNameSpecifier.h +++ /dev/null @@ -1,516 +0,0 @@ -//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- 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 NestedNameSpecifier class, which represents -// a C++ nested-name-specifier. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H -#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H - -#include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -class ASTContext; -class CXXRecordDecl; -class NamespaceAliasDecl; -class NamespaceDecl; -class IdentifierInfo; -struct PrintingPolicy; -class Type; -class TypeLoc; -class LangOptions; - -/// \brief Represents a C++ nested name specifier, such as -/// "\::std::vector<int>::". -/// -/// C++ nested name specifiers are the prefixes to qualified -/// namespaces. For example, "foo::" in "foo::x" is a nested name -/// specifier. Nested name specifiers are made up of a sequence of -/// specifiers, each of which can be a namespace, type, identifier -/// (for dependent names), decltype specifier, or the global specifier ('::'). -/// The last two specifiers can only appear at the start of a -/// nested-namespace-specifier. -class NestedNameSpecifier : public llvm::FoldingSetNode { - - /// \brief Enumeration describing - enum StoredSpecifierKind { - StoredIdentifier = 0, - StoredDecl = 1, - StoredTypeSpec = 2, - StoredTypeSpecWithTemplate = 3 - }; - - /// \brief The nested name specifier that precedes this nested name - /// specifier. - /// - /// The pointer is the nested-name-specifier that precedes this - /// one. The integer stores one of the first four values of type - /// SpecifierKind. - llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; - - /// \brief The last component in the nested name specifier, which - /// can be an identifier, a declaration, or a type. - /// - /// When the pointer is NULL, this specifier represents the global - /// specifier '::'. Otherwise, the pointer is one of - /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of - /// specifier as encoded within the prefix. - void* Specifier; - -public: - /// \brief The kind of specifier that completes this nested name - /// specifier. - enum SpecifierKind { - /// \brief An identifier, stored as an IdentifierInfo*. - Identifier, - /// \brief A namespace, stored as a NamespaceDecl*. - Namespace, - /// \brief A namespace alias, stored as a NamespaceAliasDecl*. - NamespaceAlias, - /// \brief A type, stored as a Type*. - TypeSpec, - /// \brief A type that was preceded by the 'template' keyword, - /// stored as a Type*. - TypeSpecWithTemplate, - /// \brief The global specifier '::'. There is no stored value. - Global, - /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of - /// the class it appeared in. - Super - }; - -private: - /// \brief Builds the global specifier. - NestedNameSpecifier() - : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {} - - /// \brief Copy constructor used internally to clone nested name - /// specifiers. - NestedNameSpecifier(const NestedNameSpecifier &Other) - : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), - Specifier(Other.Specifier) { - } - - void operator=(const NestedNameSpecifier &) = delete; - - /// \brief Either find or insert the given nested name specifier - /// mockup in the given context. - static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, - const NestedNameSpecifier &Mockup); - -public: - /// \brief Builds a specifier combining a prefix and an identifier. - /// - /// The prefix must be dependent, since nested name specifiers - /// referencing an identifier are only permitted when the identifier - /// cannot be resolved. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - IdentifierInfo *II); - - /// \brief Builds a nested name specifier that names a namespace. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceDecl *NS); - - /// \brief Builds a nested name specifier that names a namespace alias. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - NamespaceAliasDecl *Alias); - - /// \brief Builds a nested name specifier that names a type. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - bool Template, const Type *T); - - /// \brief Builds a specifier that consists of just an identifier. - /// - /// The nested-name-specifier is assumed to be dependent, but has no - /// prefix because the prefix is implied by something outside of the - /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent - /// type. - static NestedNameSpecifier *Create(const ASTContext &Context, - IdentifierInfo *II); - - /// \brief Returns the nested name specifier representing the global - /// scope. - static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); - - /// \brief Returns the nested name specifier representing the __super scope - /// for the given CXXRecordDecl. - static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, - CXXRecordDecl *RD); - - /// \brief Return the prefix of this nested name specifier. - /// - /// The prefix contains all of the parts of the nested name - /// specifier that preced this current specifier. For example, for a - /// nested name specifier that represents "foo::bar::", the current - /// specifier will contain "bar::" and the prefix will contain - /// "foo::". - NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } - - /// \brief Determine what kind of nested name specifier is stored. - SpecifierKind getKind() const; - - /// \brief Retrieve the identifier stored in this nested name - /// specifier. - IdentifierInfo *getAsIdentifier() const { - if (Prefix.getInt() == StoredIdentifier) - return (IdentifierInfo *)Specifier; - - return nullptr; - } - - /// \brief Retrieve the namespace stored in this nested name - /// specifier. - NamespaceDecl *getAsNamespace() const; - - /// \brief Retrieve the namespace alias stored in this nested name - /// specifier. - NamespaceAliasDecl *getAsNamespaceAlias() const; - - /// \brief Retrieve the record declaration stored in this nested name - /// specifier. - CXXRecordDecl *getAsRecordDecl() const; - - /// \brief Retrieve the type stored in this nested name specifier. - const Type *getAsType() const { - if (Prefix.getInt() == StoredTypeSpec || - Prefix.getInt() == StoredTypeSpecWithTemplate) - return (const Type *)Specifier; - - return nullptr; - } - - /// \brief Whether this nested name specifier refers to a dependent - /// type or not. - bool isDependent() const; - - /// \brief Whether this nested name specifier involves a template - /// parameter. - bool isInstantiationDependent() const; - - /// \brief Whether this nested-name-specifier contains an unexpanded - /// parameter pack (for C++11 variadic templates). - bool containsUnexpandedParameterPack() const; - - /// \brief Print this nested name specifier to the given output - /// stream. - void print(raw_ostream &OS, const PrintingPolicy &Policy) const; - - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddPointer(Prefix.getOpaqueValue()); - ID.AddPointer(Specifier); - } - - /// \brief Dump the nested name specifier to standard output to aid - /// in debugging. - void dump(const LangOptions &LO) const; - void dump() const; -}; - -/// \brief A C++ nested-name-specifier augmented with source location -/// information. -class NestedNameSpecifierLoc { - NestedNameSpecifier *Qualifier; - void *Data; - - /// \brief Determines the data length for the last component in the - /// given nested-name-specifier. - static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); - - /// \brief Determines the data length for the entire - /// nested-name-specifier. - static unsigned getDataLength(NestedNameSpecifier *Qualifier); - -public: - /// \brief Construct an empty nested-name-specifier. - NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { } - - /// \brief Construct a nested-name-specifier with source location information - /// from - NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) - : Qualifier(Qualifier), Data(Data) { } - - /// \brief Evalutes true when this nested-name-specifier location is - /// non-empty. - explicit operator bool() const { return Qualifier; } - - /// \brief Evalutes true when this nested-name-specifier location is - /// empty. - bool hasQualifier() const { return Qualifier; } - - /// \brief Retrieve the nested-name-specifier to which this instance - /// refers. - NestedNameSpecifier *getNestedNameSpecifier() const { - return Qualifier; - } - - /// \brief Retrieve the opaque pointer that refers to source-location data. - void *getOpaqueData() const { return Data; } - - /// \brief Retrieve the source range covering the entirety of this - /// nested-name-specifier. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector<int>::, the returned source range would cover - /// from the initial '::' to the last '::'. - SourceRange getSourceRange() const LLVM_READONLY; - - /// \brief Retrieve the source range covering just the last part of - /// this nested-name-specifier, not including the prefix. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector<int>::, the returned source range would cover - /// from "vector" to the last '::'. - SourceRange getLocalSourceRange() const; - - /// \brief Retrieve the location of the beginning of this - /// nested-name-specifier. - SourceLocation getBeginLoc() const { - return getSourceRange().getBegin(); - } - - /// \brief Retrieve the location of the end of this - /// nested-name-specifier. - SourceLocation getEndLoc() const { - return getSourceRange().getEnd(); - } - - /// \brief Retrieve the location of the beginning of this - /// component of the nested-name-specifier. - SourceLocation getLocalBeginLoc() const { - return getLocalSourceRange().getBegin(); - } - - /// \brief Retrieve the location of the end of this component of the - /// nested-name-specifier. - SourceLocation getLocalEndLoc() const { - return getLocalSourceRange().getEnd(); - } - - /// \brief Return the prefix of this nested-name-specifier. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the - /// returned prefix may be empty, if this is the first component of - /// the nested-name-specifier. - NestedNameSpecifierLoc getPrefix() const { - if (!Qualifier) - return *this; - - return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); - } - - /// \brief For a nested-name-specifier that refers to a type, - /// retrieve the type with source-location information. - TypeLoc getTypeLoc() const; - - /// \brief Determines the data length for the entire - /// nested-name-specifier. - unsigned getDataLength() const { return getDataLength(Qualifier); } - - friend bool operator==(NestedNameSpecifierLoc X, - NestedNameSpecifierLoc Y) { - return X.Qualifier == Y.Qualifier && X.Data == Y.Data; - } - - friend bool operator!=(NestedNameSpecifierLoc X, - NestedNameSpecifierLoc Y) { - return !(X == Y); - } -}; - -/// \brief Class that aids in the construction of nested-name-specifiers along -/// with source-location information for all of the components of the -/// nested-name-specifier. -class NestedNameSpecifierLocBuilder { - /// \brief The current representation of the nested-name-specifier we're - /// building. - NestedNameSpecifier *Representation; - - /// \brief Buffer used to store source-location information for the - /// nested-name-specifier. - /// - /// Note that we explicitly manage the buffer (rather than using a - /// SmallVector) because \c Declarator expects it to be possible to memcpy() - /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. - char *Buffer; - - /// \brief The size of the buffer used to store source-location information - /// for the nested-name-specifier. - unsigned BufferSize; - - /// \brief The capacity of the buffer used to store source-location - /// information for the nested-name-specifier. - unsigned BufferCapacity; - -public: - NestedNameSpecifierLocBuilder() - : Representation(nullptr), Buffer(nullptr), BufferSize(0), - BufferCapacity(0) {} - - NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); - - NestedNameSpecifierLocBuilder & - operator=(const NestedNameSpecifierLocBuilder &Other); - - ~NestedNameSpecifierLocBuilder() { - if (BufferCapacity) - free(Buffer); - } - - /// \brief Retrieve the representation of the nested-name-specifier. - NestedNameSpecifier *getRepresentation() const { return Representation; } - - /// \brief Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'type::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param TemplateKWLoc The location of the 'template' keyword, if present. - /// - /// \param TL The TypeLoc that describes the type preceding the '::'. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, - SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'identifier::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Identifier The identifier. - /// - /// \param IdentifierLoc The location of the identifier. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, IdentifierInfo *Identifier, - SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Namespace The namespace. - /// - /// \param NamespaceLoc The location of the namespace name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceDecl *Namespace, - SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace-alias::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Alias The namespace alias. - /// - /// \param AliasLoc The location of the namespace alias - /// name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, - SourceLocation AliasLoc, SourceLocation ColonColonLoc); - - /// \brief Turn this (empty) nested-name-specifier into the global - /// nested-name-specifier '::'. - void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); - - /// \brief Turns this (empty) nested-name-specifier into '__super' - /// nested-name-specifier. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param RD The declaration of the class in which nested-name-specifier - /// appeared. - /// - /// \param SuperLoc The location of the '__super' keyword. - /// name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, - SourceLocation SuperLoc, SourceLocation ColonColonLoc); - /// \brief Make a new nested-name-specifier from incomplete source-location - /// information. - /// - /// This routine should be used very, very rarely, in cases where we - /// need to synthesize a nested-name-specifier. Most code should instead use - /// \c Adopt() with a proper \c NestedNameSpecifierLoc. - void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, - SourceRange R); - - /// \brief Adopt an existing nested-name-specifier (with source-range - /// information). - void Adopt(NestedNameSpecifierLoc Other); - - /// \brief Retrieve the source range covered by this nested-name-specifier. - SourceRange getSourceRange() const LLVM_READONLY { - return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); - } - - /// \brief Retrieve a nested-name-specifier with location information, - /// copied into the given AST context. - /// - /// \param Context The context into which this nested-name-specifier will be - /// copied. - NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; - - /// \brief Retrieve a nested-name-specifier with location - /// information based on the information in this builder. - /// - /// This loc will contain references to the builder's internal data and may - /// be invalidated by any change to the builder. - NestedNameSpecifierLoc getTemporary() const { - return NestedNameSpecifierLoc(Representation, Buffer); - } - - /// \brief Clear out this builder, and prepare it to build another - /// nested-name-specifier with source-location information. - void Clear() { - Representation = nullptr; - BufferSize = 0; - } - - /// \brief Retrieve the underlying buffer. - /// - /// \returns A pair containing a pointer to the buffer of source-location - /// data and the size of the source-location data that resides in that - /// buffer. - std::pair<char *, unsigned> getBuffer() const { - return std::make_pair(Buffer, BufferSize); - } -}; - -/// Insertion operator for diagnostics. This allows sending -/// NestedNameSpecifiers into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - NestedNameSpecifier *NNS) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), - DiagnosticsEngine::ak_nestednamespec); - return DB; -} - -} - -#endif diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h deleted file mode 100644 index 7632a4b..0000000 --- a/include/clang/AST/OpenMPClause.h +++ /dev/null @@ -1,3198 +0,0 @@ -//===- OpenMPClause.h - Classes for OpenMP clauses --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// \brief This file defines OpenMP AST classes for clauses. -/// There are clauses for executable directives, clauses for declarative -/// directives and clauses which can be used in both kinds of directives. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H -#define LLVM_CLANG_AST_OPENMPCLAUSE_H - -#include "clang/AST/Expr.h" -#include "clang/AST/Stmt.h" -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/SourceLocation.h" - -namespace clang { - -//===----------------------------------------------------------------------===// -// AST classes for clauses. -//===----------------------------------------------------------------------===// - -/// \brief This is a basic class for representing single OpenMP clause. -/// -class OMPClause { - /// \brief Starting location of the clause (the clause keyword). - SourceLocation StartLoc; - /// \brief Ending location of the clause. - SourceLocation EndLoc; - /// \brief Kind of the clause. - OpenMPClauseKind Kind; - -protected: - OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc) - : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {} - -public: - /// \brief Returns the starting location of the clause. - SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns the ending location of the clause. - SourceLocation getLocEnd() const { return EndLoc; } - - /// \brief Sets the starting location of the clause. - void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Sets the ending location of the clause. - void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } - - /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.). - OpenMPClauseKind getClauseKind() const { return Kind; } - - bool isImplicit() const { return StartLoc.isInvalid(); } - - typedef StmtIterator child_iterator; - typedef ConstStmtIterator const_child_iterator; - typedef llvm::iterator_range<child_iterator> child_range; - typedef llvm::iterator_range<const_child_iterator> const_child_range; - - child_range children(); - const_child_range children() const { - auto Children = const_cast<OMPClause *>(this)->children(); - return const_child_range(Children.begin(), Children.end()); - } - static bool classof(const OMPClause *) { return true; } -}; - -/// \brief This represents clauses with the list of variables like 'private', -/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the -/// '#pragma omp ...' directives. -template <class T> class OMPVarListClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Number of variables in the list. - unsigned NumVars; - -protected: - /// \brief Fetches list of variables associated with this clause. - MutableArrayRef<Expr *> getVarRefs() { - return MutableArrayRef<Expr *>( - static_cast<T *>(this)->template getTrailingObjects<Expr *>(), NumVars); - } - - /// \brief Sets the list of variables for this clause. - void setVarRefs(ArrayRef<Expr *> VL) { - assert(VL.size() == NumVars && - "Number of variables is not the same as the preallocated buffer"); - std::copy(VL.begin(), VL.end(), - static_cast<T *>(this)->template getTrailingObjects<Expr *>()); - } - - /// \brief Build a clause with \a N variables - /// - /// \param K Kind of the clause. - /// \param StartLoc Starting location of the clause (the clause keyword). - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {} - -public: - typedef MutableArrayRef<Expr *>::iterator varlist_iterator; - typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; - typedef llvm::iterator_range<varlist_iterator> varlist_range; - typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; - - unsigned varlist_size() const { return NumVars; } - bool varlist_empty() const { return NumVars == 0; } - - varlist_range varlists() { - return varlist_range(varlist_begin(), varlist_end()); - } - varlist_const_range varlists() const { - return varlist_const_range(varlist_begin(), varlist_end()); - } - - varlist_iterator varlist_begin() { return getVarRefs().begin(); } - varlist_iterator varlist_end() { return getVarRefs().end(); } - varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); } - varlist_const_iterator varlist_end() const { return getVarRefs().end(); } - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Fetches list of all variables in the clause. - ArrayRef<const Expr *> getVarRefs() const { - return llvm::makeArrayRef( - static_cast<const T *>(this)->template getTrailingObjects<Expr *>(), - NumVars); - } -}; - -/// \brief This represents 'if' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp parallel if(parallel:a > 5) -/// \endcode -/// In this example directive '#pragma omp parallel' has simple 'if' clause with -/// condition 'a > 5' and directive name modifier 'parallel'. -/// -class OMPIfClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Condition of the 'if' clause. - Stmt *Condition; - /// \brief Location of ':' (if any). - SourceLocation ColonLoc; - /// \brief Directive name modifier for the clause. - OpenMPDirectiveKind NameModifier; - /// \brief Name modifier location. - SourceLocation NameModifierLoc; - - /// \brief Set condition. - /// - void setCondition(Expr *Cond) { Condition = Cond; } - /// \brief Set directive name modifier for the clause. - /// - void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; } - /// \brief Set location of directive name modifier for the clause. - /// - void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; } - /// \brief Set location of ':'. - /// - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - -public: - /// \brief Build 'if' clause with condition \a Cond. - /// - /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause. - /// \param Cond Condition of the clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param NameModifierLoc Location of directive name modifier. - /// \param ColonLoc [OpenMP 4.1] Location of ':'. - /// \param EndLoc Ending location of the clause. - /// - OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation NameModifierLoc, SourceLocation ColonLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc), - Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier), - NameModifierLoc(NameModifierLoc) {} - - /// \brief Build an empty clause. - /// - OMPIfClause() - : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(), - Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown), - NameModifierLoc() {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return the location of ':'. - SourceLocation getColonLoc() const { return ColonLoc; } - - /// \brief Returns condition. - Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - /// \brief Return directive name modifier associated with the clause. - OpenMPDirectiveKind getNameModifier() const { return NameModifier; } - - /// \brief Return the location of directive name modifier. - SourceLocation getNameModifierLoc() const { return NameModifierLoc; } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_if; - } - - child_range children() { return child_range(&Condition, &Condition + 1); } -}; - -/// \brief This represents 'final' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp task final(a > 5) -/// \endcode -/// In this example directive '#pragma omp task' has simple 'final' -/// clause with condition 'a > 5'. -/// -class OMPFinalClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Condition of the 'if' clause. - Stmt *Condition; - - /// \brief Set condition. - /// - void setCondition(Expr *Cond) { Condition = Cond; } - -public: - /// \brief Build 'final' clause with condition \a Cond. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param Cond Condition of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), - Condition(Cond) {} - - /// \brief Build an empty clause. - /// - OMPFinalClause() - : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Condition(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Returns condition. - Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_final; - } - - child_range children() { return child_range(&Condition, &Condition + 1); } -}; - -/// \brief This represents 'num_threads' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp parallel num_threads(6) -/// \endcode -/// In this example directive '#pragma omp parallel' has simple 'num_threads' -/// clause with number of threads '6'. -/// -class OMPNumThreadsClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Condition of the 'num_threads' clause. - Stmt *NumThreads; - - /// \brief Set condition. - /// - void setNumThreads(Expr *NThreads) { NumThreads = NThreads; } - -public: - /// \brief Build 'num_threads' clause with condition \a NumThreads. - /// - /// \param NumThreads Number of threads for the construct. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumThreads(NumThreads) {} - - /// \brief Build an empty clause. - /// - OMPNumThreadsClause() - : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumThreads(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Returns number of threads. - Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_threads; - } - - child_range children() { return child_range(&NumThreads, &NumThreads + 1); } -}; - -/// \brief This represents 'safelen' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp simd safelen(4) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'safelen' -/// with single expression '4'. -/// If the safelen clause is used then no two iterations executed -/// concurrently with SIMD instructions can have a greater distance -/// in the logical iteration space than its value. The parameter of -/// the safelen clause must be a constant positive integer expression. -/// -class OMPSafelenClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Safe iteration space distance. - Stmt *Safelen; - - /// \brief Set safelen. - void setSafelen(Expr *Len) { Safelen = Len; } - -public: - /// \brief Build 'safelen' clause. - /// - /// \param Len Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), - Safelen(Len) {} - - /// \brief Build an empty clause. - /// - explicit OMPSafelenClause() - : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Safelen(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return safe iteration space distance. - Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_safelen; - } - - child_range children() { return child_range(&Safelen, &Safelen + 1); } -}; - -/// \brief This represents 'simdlen' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp simd simdlen(4) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'simdlen' -/// with single expression '4'. -/// If the 'simdlen' clause is used then it specifies the preferred number of -/// iterations to be executed concurrently. The parameter of the 'simdlen' -/// clause must be a constant positive integer expression. -/// -class OMPSimdlenClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Safe iteration space distance. - Stmt *Simdlen; - - /// \brief Set simdlen. - void setSimdlen(Expr *Len) { Simdlen = Len; } - -public: - /// \brief Build 'simdlen' clause. - /// - /// \param Len Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc), - Simdlen(Len) {} - - /// \brief Build an empty clause. - /// - explicit OMPSimdlenClause() - : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Simdlen(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return safe iteration space distance. - Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_simdlen; - } - - child_range children() { return child_range(&Simdlen, &Simdlen + 1); } -}; - -/// \brief This represents 'collapse' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp simd collapse(3) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'collapse' -/// with single expression '3'. -/// The parameter must be a constant positive integer expression, it specifies -/// the number of nested loops that should be collapsed into a single iteration -/// space. -/// -class OMPCollapseClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Number of for-loops. - Stmt *NumForLoops; - - /// \brief Set the number of associated for-loops. - void setNumForLoops(Expr *Num) { NumForLoops = Num; } - -public: - /// \brief Build 'collapse' clause. - /// - /// \param Num Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPCollapseClause(Expr *Num, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumForLoops(Num) {} - - /// \brief Build an empty clause. - /// - explicit OMPCollapseClause() - : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumForLoops(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return the number of associated for-loops. - Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_collapse; - } - - child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } -}; - -/// \brief This represents 'default' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp parallel default(shared) -/// \endcode -/// In this example directive '#pragma omp parallel' has simple 'default' -/// clause with kind 'shared'. -/// -class OMPDefaultClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief A kind of the 'default' clause. - OpenMPDefaultClauseKind Kind; - /// \brief Start location of the kind in source code. - SourceLocation KindKwLoc; - - /// \brief Set kind of the clauses. - /// - /// \param K Argument of clause. - /// - void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } - - /// \brief Set argument location. - /// - /// \param KLoc Argument location. - /// - void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } - -public: - /// \brief Build 'default' clause with argument \a A ('none' or 'shared'). - /// - /// \param A Argument of the clause ('none' or 'shared'). - /// \param ALoc Starting location of the argument. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(A), KindKwLoc(ALoc) {} - - /// \brief Build an empty clause. - /// - OMPDefaultClause() - : OMPClause(OMPC_default, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown), - KindKwLoc(SourceLocation()) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Returns kind of the clause. - OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } - - /// \brief Returns location of clause kind. - SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_default; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp parallel proc_bind(master) -/// \endcode -/// In this example directive '#pragma omp parallel' has simple 'proc_bind' -/// clause with kind 'master'. -/// -class OMPProcBindClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief A kind of the 'proc_bind' clause. - OpenMPProcBindClauseKind Kind; - /// \brief Start location of the kind in source code. - SourceLocation KindKwLoc; - - /// \brief Set kind of the clause. - /// - /// \param K Kind of clause. - /// - void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; } - - /// \brief Set clause kind location. - /// - /// \param KLoc Kind location. - /// - void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } - -public: - /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or - /// 'spread'). - /// - /// \param A Argument of the clause ('master', 'close' or 'spread'). - /// \param ALoc Starting location of the argument. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(A), KindKwLoc(ALoc) {} - - /// \brief Build an empty clause. - /// - OMPProcBindClause() - : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown), - KindKwLoc(SourceLocation()) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Returns kind of the clause. - OpenMPProcBindClauseKind getProcBindKind() const { return Kind; } - - /// \brief Returns location of clause kind. - SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_proc_bind; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp for schedule(static, 3) -/// \endcode -/// In this example directive '#pragma omp for' has 'schedule' clause with -/// arguments 'static' and '3'. -/// -class OMPScheduleClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief A kind of the 'schedule' clause. - OpenMPScheduleClauseKind Kind; - /// \brief Modifiers for 'schedule' clause. - enum {FIRST, SECOND, NUM_MODIFIERS}; - OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS]; - /// \brief Locations of modifiers. - SourceLocation ModifiersLoc[NUM_MODIFIERS]; - /// \brief Start location of the schedule ind in source code. - SourceLocation KindLoc; - /// \brief Location of ',' (if any). - SourceLocation CommaLoc; - /// \brief Chunk size and a reference to pseudo variable for combined - /// directives. - enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS }; - Stmt *ChunkSizes[NUM_EXPRS]; - - /// \brief Set schedule kind. - /// - /// \param K Schedule kind. - /// - void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; } - /// \brief Set the first schedule modifier. - /// - /// \param M Schedule modifier. - /// - void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) { - Modifiers[FIRST] = M; - } - /// \brief Set the second schedule modifier. - /// - /// \param M Schedule modifier. - /// - void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) { - Modifiers[SECOND] = M; - } - /// \brief Set location of the first schedule modifier. - /// - void setFirstScheduleModifierLoc(SourceLocation Loc) { - ModifiersLoc[FIRST] = Loc; - } - /// \brief Set location of the second schedule modifier. - /// - void setSecondScheduleModifierLoc(SourceLocation Loc) { - ModifiersLoc[SECOND] = Loc; - } - /// \brief Set schedule modifier location. - /// - /// \param M Schedule modifier location. - /// - void setScheduleModifer(OpenMPScheduleClauseModifier M) { - if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown) - Modifiers[FIRST] = M; - else { - assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown); - Modifiers[SECOND] = M; - } - } - /// \brief Sets the location of '('. - /// - /// \param Loc Location of '('. - /// - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Set schedule kind start location. - /// - /// \param KLoc Schedule kind location. - /// - void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } - /// \brief Set location of ','. - /// - /// \param Loc Location of ','. - /// - void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } - /// \brief Set chunk size. - /// - /// \param E Chunk size. - /// - void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; } - /// \brief Set helper chunk size. - /// - /// \param E Helper chunk size. - /// - void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; } - -public: - /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size - /// expression \a ChunkSize. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param KLoc Starting location of the argument. - /// \param CommaLoc Location of ','. - /// \param EndLoc Ending location of the clause. - /// \param Kind Schedule kind. - /// \param ChunkSize Chunk size. - /// \param HelperChunkSize Helper chunk size for combined directives. - /// \param M1 The first modifier applied to 'schedule' clause. - /// \param M1Loc Location of the first modifier - /// \param M2 The second modifier applied to 'schedule' clause. - /// \param M2Loc Location of the second modifier - /// - OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation KLoc, SourceLocation CommaLoc, - SourceLocation EndLoc, OpenMPScheduleClauseKind Kind, - Expr *ChunkSize, Expr *HelperChunkSize, - OpenMPScheduleClauseModifier M1, SourceLocation M1Loc, - OpenMPScheduleClauseModifier M2, SourceLocation M2Loc) - : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) { - ChunkSizes[CHUNK_SIZE] = ChunkSize; - ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize; - Modifiers[FIRST] = M1; - Modifiers[SECOND] = M2; - ModifiersLoc[FIRST] = M1Loc; - ModifiersLoc[SECOND] = M2Loc; - } - - /// \brief Build an empty clause. - /// - explicit OMPScheduleClause() - : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), - Kind(OMPC_SCHEDULE_unknown) { - ChunkSizes[CHUNK_SIZE] = nullptr; - ChunkSizes[HELPER_CHUNK_SIZE] = nullptr; - Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown; - Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown; - } - - /// \brief Get kind of the clause. - /// - OpenMPScheduleClauseKind getScheduleKind() const { return Kind; } - /// \brief Get the first modifier of the clause. - /// - OpenMPScheduleClauseModifier getFirstScheduleModifier() const { - return Modifiers[FIRST]; - } - /// \brief Get the second modifier of the clause. - /// - OpenMPScheduleClauseModifier getSecondScheduleModifier() const { - return Modifiers[SECOND]; - } - /// \brief Get location of '('. - /// - SourceLocation getLParenLoc() { return LParenLoc; } - /// \brief Get kind location. - /// - SourceLocation getScheduleKindLoc() { return KindLoc; } - /// \brief Get the first modifier location. - /// - SourceLocation getFirstScheduleModifierLoc() const { - return ModifiersLoc[FIRST]; - } - /// \brief Get the second modifier location. - /// - SourceLocation getSecondScheduleModifierLoc() const { - return ModifiersLoc[SECOND]; - } - /// \brief Get location of ','. - /// - SourceLocation getCommaLoc() { return CommaLoc; } - /// \brief Get chunk size. - /// - Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]); } - /// \brief Get chunk size. - /// - Expr *getChunkSize() const { - return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]); - } - /// \brief Get helper chunk size. - /// - Expr *getHelperChunkSize() { - return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]); - } - /// \brief Get helper chunk size. - /// - Expr *getHelperChunkSize() const { - return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_schedule; - } - - child_range children() { - return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1); - } -}; - -/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp for ordered (2) -/// \endcode -/// In this example directive '#pragma omp for' has 'ordered' clause with -/// parameter 2. -/// -class OMPOrderedClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Number of for-loops. - Stmt *NumForLoops; - - /// \brief Set the number of associated for-loops. - void setNumForLoops(Expr *Num) { NumForLoops = Num; } - -public: - /// \brief Build 'ordered' clause. - /// - /// \param Num Expression, possibly associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPOrderedClause(Expr *Num, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumForLoops(Num) {} - - /// \brief Build an empty clause. - /// - explicit OMPOrderedClause() - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumForLoops(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return the number of associated for-loops. - Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_ordered; - } - - child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } -}; - -/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp for nowait -/// \endcode -/// In this example directive '#pragma omp for' has 'nowait' clause. -/// -class OMPNowaitClause : public OMPClause { -public: - /// \brief Build 'nowait' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_nowait, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPNowaitClause() - : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nowait; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'untied' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp task untied -/// \endcode -/// In this example directive '#pragma omp task' has 'untied' clause. -/// -class OMPUntiedClause : public OMPClause { -public: - /// \brief Build 'untied' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_untied, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPUntiedClause() - : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_untied; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'mergeable' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp task mergeable -/// \endcode -/// In this example directive '#pragma omp task' has 'mergeable' clause. -/// -class OMPMergeableClause : public OMPClause { -public: - /// \brief Build 'mergeable' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPMergeableClause() - : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_mergeable; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'read' clause in the '#pragma omp atomic' directive. -/// -/// \code -/// #pragma omp atomic read -/// \endcode -/// In this example directive '#pragma omp atomic' has 'read' clause. -/// -class OMPReadClause : public OMPClause { -public: - /// \brief Build 'read' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_read, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_read; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'write' clause in the '#pragma omp atomic' directive. -/// -/// \code -/// #pragma omp atomic write -/// \endcode -/// In this example directive '#pragma omp atomic' has 'write' clause. -/// -class OMPWriteClause : public OMPClause { -public: - /// \brief Build 'write' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_write, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPWriteClause() - : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_write; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'update' clause in the '#pragma omp atomic' -/// directive. -/// -/// \code -/// #pragma omp atomic update -/// \endcode -/// In this example directive '#pragma omp atomic' has 'update' clause. -/// -class OMPUpdateClause : public OMPClause { -public: - /// \brief Build 'update' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_update, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPUpdateClause() - : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_update; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'capture' clause in the '#pragma omp atomic' -/// directive. -/// -/// \code -/// #pragma omp atomic capture -/// \endcode -/// In this example directive '#pragma omp atomic' has 'capture' clause. -/// -class OMPCaptureClause : public OMPClause { -public: - /// \brief Build 'capture' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_capture, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPCaptureClause() - : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_capture; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' -/// directive. -/// -/// \code -/// #pragma omp atomic seq_cst -/// \endcode -/// In this example directive '#pragma omp atomic' has 'seq_cst' clause. -/// -class OMPSeqCstClause : public OMPClause { -public: - /// \brief Build 'seq_cst' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPSeqCstClause() - : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_seq_cst; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents clause 'private' in the '#pragma omp ...' directives. -/// -/// \code -/// #pragma omp parallel private(a,b) -/// \endcode -/// In this example directive '#pragma omp parallel' has clause 'private' -/// with the variables 'a' and 'b'. -/// -class OMPPrivateClause final - : public OMPVarListClause<OMPPrivateClause>, - private llvm::TrailingObjects<OMPPrivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc, - EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPPrivateClause(unsigned N) - : OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(), - SourceLocation(), SourceLocation(), - N) {} - - /// \brief Sets the list of references to private copies with initializers for - /// new private variables. - /// \param VL List of references. - void setPrivateCopies(ArrayRef<Expr *> VL); - - /// \brief Gets the list of references to private copies with initializers for - /// new private variables. - MutableArrayRef<Expr *> getPrivateCopies() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param PrivateVL List of references to private copies with initializers. - /// - static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, - ArrayRef<Expr *> PrivateVL); - /// \brief Creates an empty clause with the place for \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; - typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; - typedef llvm::iterator_range<private_copies_iterator> private_copies_range; - typedef llvm::iterator_range<private_copies_const_iterator> - private_copies_const_range; - - private_copies_range private_copies() { - return private_copies_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - private_copies_const_range private_copies() const { - return private_copies_const_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_private; - } -}; - -/// \brief This represents clause 'firstprivate' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp parallel firstprivate(a,b) -/// \endcode -/// In this example directive '#pragma omp parallel' has clause 'firstprivate' -/// with the variables 'a' and 'b'. -/// -class OMPFirstprivateClause final - : public OMPVarListClause<OMPFirstprivateClause>, - private llvm::TrailingObjects<OMPFirstprivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc, - LParenLoc, EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPFirstprivateClause(unsigned N) - : OMPVarListClause<OMPFirstprivateClause>( - OMPC_firstprivate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} - /// \brief Sets the list of references to private copies with initializers for - /// new private variables. - /// \param VL List of references. - void setPrivateCopies(ArrayRef<Expr *> VL); - - /// \brief Gets the list of references to private copies with initializers for - /// new private variables. - MutableArrayRef<Expr *> getPrivateCopies() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - /// \brief Sets the list of references to initializer variables for new - /// private variables. - /// \param VL List of references. - void setInits(ArrayRef<Expr *> VL); - - /// \brief Gets the list of references to initializer variables for new - /// private variables. - MutableArrayRef<Expr *> getInits() { - return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); - } - ArrayRef<const Expr *> getInits() const { - return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the original variables. - /// \param PrivateVL List of references to private copies with initializers. - /// \param InitVL List of references to auto generated variables used for - /// initialization of a single array element. Used if firstprivate variable is - /// of array type. - /// - static OMPFirstprivateClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, - ArrayRef<Expr *> InitVL); - /// \brief Creates an empty clause with the place for \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; - typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; - typedef llvm::iterator_range<private_copies_iterator> private_copies_range; - typedef llvm::iterator_range<private_copies_const_iterator> - private_copies_const_range; - - private_copies_range private_copies() { - return private_copies_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - private_copies_const_range private_copies() const { - return private_copies_const_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - - typedef MutableArrayRef<Expr *>::iterator inits_iterator; - typedef ArrayRef<const Expr *>::iterator inits_const_iterator; - typedef llvm::iterator_range<inits_iterator> inits_range; - typedef llvm::iterator_range<inits_const_iterator> inits_const_range; - - inits_range inits() { - return inits_range(getInits().begin(), getInits().end()); - } - inits_const_range inits() const { - return inits_const_range(getInits().begin(), getInits().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_firstprivate; - } -}; - -/// \brief This represents clause 'lastprivate' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp simd lastprivate(a,b) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'lastprivate' -/// with the variables 'a' and 'b'. -class OMPLastprivateClause final - : public OMPVarListClause<OMPLastprivateClause>, - private llvm::TrailingObjects<OMPLastprivateClause, Expr *> { - // There are 4 additional tail-allocated arrays at the end of the class: - // 1. Contains list of pseudo variables with the default initialization for - // each non-firstprivate variables. Used in codegen for initialization of - // lastprivate copies. - // 2. List of helper expressions for proper generation of assignment operation - // required for lastprivate clause. This list represents private variables - // (for arrays, single array element). - // 3. List of helper expressions for proper generation of assignment operation - // required for lastprivate clause. This list represents original variables - // (for arrays, single array element). - // 4. List of helper expressions that represents assignment operation: - // \code - // DstExprs = SrcExprs; - // \endcode - // Required for proper codegen of final assignment performed by the - // lastprivate clause. - // - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc, - LParenLoc, EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPLastprivateClause(unsigned N) - : OMPVarListClause<OMPLastprivateClause>( - OMPC_lastprivate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} - - /// \brief Get the list of helper expressions for initialization of private - /// copies for lastprivate variables. - MutableArrayRef<Expr *> getPrivateCopies() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent private variables (for arrays, single - /// array element) in the final assignment statement performed by the - /// lastprivate clause. - void setSourceExprs(ArrayRef<Expr *> SrcExprs); - - /// \brief Get the list of helper source expressions. - MutableArrayRef<Expr *> getSourceExprs() { - return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); - } - ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent original variables (for arrays, single - /// array element) in the final assignment statement performed by the - /// lastprivate clause. - void setDestinationExprs(ArrayRef<Expr *> DstExprs); - - /// \brief Get the list of helper destination expressions. - MutableArrayRef<Expr *> getDestinationExprs() { - return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); - } - - /// \brief Set list of helper assignment expressions, required for proper - /// codegen of the clause. These expressions are assignment expressions that - /// assign private copy of the variable to original variable. - void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - - /// \brief Get the list of helper assignment expressions. - MutableArrayRef<Expr *> getAssignmentOps() { - return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param SrcExprs List of helper expressions for proper generation of - /// assignment operation required for lastprivate clause. This list represents - /// private variables (for arrays, single array element). - /// \param DstExprs List of helper expressions for proper generation of - /// assignment operation required for lastprivate clause. This list represents - /// original variables (for arrays, single array element). - /// \param AssignmentOps List of helper expressions that represents assignment - /// operation: - /// \code - /// DstExprs = SrcExprs; - /// \endcode - /// Required for proper codegen of final assignment performed by the - /// lastprivate clause. - /// - /// - static OMPLastprivateClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); - /// \brief Creates an empty clause with the place for \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; - - /// \brief Set list of helper expressions, required for generation of private - /// copies of original lastprivate variables. - void setPrivateCopies(ArrayRef<Expr *> PrivateCopies); - - helper_expr_const_range private_copies() const { - return helper_expr_const_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - helper_expr_range private_copies() { - return helper_expr_range(getPrivateCopies().begin(), - getPrivateCopies().end()); - } - helper_expr_const_range source_exprs() const { - return helper_expr_const_range(getSourceExprs().begin(), - getSourceExprs().end()); - } - helper_expr_range source_exprs() { - return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); - } - helper_expr_const_range destination_exprs() const { - return helper_expr_const_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_range destination_exprs() { - return helper_expr_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_const_range assignment_ops() const { - return helper_expr_const_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - helper_expr_range assignment_ops() { - return helper_expr_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_lastprivate; - } -}; - -/// \brief This represents clause 'shared' in the '#pragma omp ...' directives. -/// -/// \code -/// #pragma omp parallel shared(a,b) -/// \endcode -/// In this example directive '#pragma omp parallel' has clause 'shared' -/// with the variables 'a' and 'b'. -/// -class OMPSharedClause final - : public OMPVarListClause<OMPSharedClause>, - private llvm::TrailingObjects<OMPSharedClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc, - EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPSharedClause(unsigned N) - : OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(), - SourceLocation(), SourceLocation(), - N) {} - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// - static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_shared; - } -}; - -/// \brief This represents clause 'reduction' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp parallel reduction(+:a,b) -/// \endcode -/// In this example directive '#pragma omp parallel' has clause 'reduction' -/// with operator '+' and the variables 'a' and 'b'. -/// -class OMPReductionClause final - : public OMPVarListClause<OMPReductionClause>, - private llvm::TrailingObjects<OMPReductionClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Location of ':'. - SourceLocation ColonLoc; - /// \brief Nested name specifier for C++. - NestedNameSpecifierLoc QualifierLoc; - /// \brief Name of custom operator. - DeclarationNameInfo NameInfo; - - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param ColonLoc Location of ':'. - /// \param N Number of the variables in the clause. - /// \param QualifierLoc The nested-name qualifier with location information - /// \param NameInfo The full name info for reduction identifier. - /// - OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) - : OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc, - LParenLoc, EndLoc, N), - ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPReductionClause(unsigned N) - : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(), - SourceLocation(), SourceLocation(), - N), - ColonLoc(), QualifierLoc(), NameInfo() {} - - /// \brief Sets location of ':' symbol in clause. - void setColonLoc(SourceLocation CL) { ColonLoc = CL; } - /// \brief Sets the name info for specified reduction identifier. - void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } - /// \brief Sets the nested name specifier. - void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent private copy of the reduction - /// variable. - void setPrivates(ArrayRef<Expr *> Privates); - - /// \brief Get the list of helper privates. - MutableArrayRef<Expr *> getPrivates() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent LHS expression in the final - /// reduction expression performed by the reduction clause. - void setLHSExprs(ArrayRef<Expr *> LHSExprs); - - /// \brief Get the list of helper LHS expressions. - MutableArrayRef<Expr *> getLHSExprs() { - return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); - } - ArrayRef<const Expr *> getLHSExprs() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent RHS expression in the final - /// reduction expression performed by the reduction clause. - /// Also, variables in these expressions are used for proper initialization of - /// reduction copies. - void setRHSExprs(ArrayRef<Expr *> RHSExprs); - - /// \brief Get the list of helper destination expressions. - MutableArrayRef<Expr *> getRHSExprs() { - return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getRHSExprs() const { - return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); - } - - /// \brief Set list of helper reduction expressions, required for proper - /// codegen of the clause. These expressions are binary expressions or - /// operator/custom reduction call that calculates new value from source - /// helper expressions to destination helper expressions. - void setReductionOps(ArrayRef<Expr *> ReductionOps); - - /// \brief Get the list of helper reduction expressions. - MutableArrayRef<Expr *> getReductionOps() { - return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getReductionOps() const { - return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param ColonLoc Location of ':'. - /// \param EndLoc Ending location of the clause. - /// \param VL The variables in the clause. - /// \param QualifierLoc The nested-name qualifier with location information - /// \param NameInfo The full name info for reduction identifier. - /// \param Privates List of helper expressions for proper generation of - /// private copies. - /// \param LHSExprs List of helper expressions for proper generation of - /// assignment operation required for copyprivate clause. This list represents - /// LHSs of the reduction expressions. - /// \param RHSExprs List of helper expressions for proper generation of - /// assignment operation required for copyprivate clause. This list represents - /// RHSs of the reduction expressions. - /// Also, variables in these expressions are used for proper initialization of - /// reduction copies. - /// \param ReductionOps List of helper expressions that represents reduction - /// expressions: - /// \code - /// LHSExprs binop RHSExprs; - /// operator binop(LHSExpr, RHSExpr); - /// <CutomReduction>(LHSExpr, RHSExpr); - /// \endcode - /// Required for proper codegen of final reduction operation performed by the - /// reduction clause. - /// - static OMPReductionClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, - ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, - ArrayRef<Expr *> ReductionOps); - /// \brief Creates an empty clause with the place for \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N); - - /// \brief Gets location of ':' symbol in clause. - SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Gets the name info for specified reduction identifier. - const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - /// \brief Gets the nested name specifier. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; - - helper_expr_const_range privates() const { - return helper_expr_const_range(getPrivates().begin(), getPrivates().end()); - } - helper_expr_range privates() { - return helper_expr_range(getPrivates().begin(), getPrivates().end()); - } - helper_expr_const_range lhs_exprs() const { - return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end()); - } - helper_expr_range lhs_exprs() { - return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end()); - } - helper_expr_const_range rhs_exprs() const { - return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end()); - } - helper_expr_range rhs_exprs() { - return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end()); - } - helper_expr_const_range reduction_ops() const { - return helper_expr_const_range(getReductionOps().begin(), - getReductionOps().end()); - } - helper_expr_range reduction_ops() { - return helper_expr_range(getReductionOps().begin(), - getReductionOps().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_reduction; - } -}; - -/// \brief This represents clause 'linear' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp simd linear(a,b : 2) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'linear' -/// with variables 'a', 'b' and linear step '2'. -/// -class OMPLinearClause final - : public OMPVarListClause<OMPLinearClause>, - private llvm::TrailingObjects<OMPLinearClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Modifier of 'linear' clause. - OpenMPLinearClauseKind Modifier; - /// \brief Location of linear modifier if any. - SourceLocation ModifierLoc; - /// \brief Location of ':'. - SourceLocation ColonLoc; - - /// \brief Sets the linear step for clause. - void setStep(Expr *Step) { *(getFinals().end()) = Step; } - - /// \brief Sets the expression to calculate linear step for clause. - void setCalcStep(Expr *CalcStep) { *(getFinals().end() + 1) = CalcStep; } - - /// \brief Build 'linear' clause with given number of variables \a NumVars. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param ColonLoc Location of ':'. - /// \param EndLoc Ending location of the clause. - /// \param NumVars Number of variables. - /// - OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc, - OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, - unsigned NumVars) - : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc, - EndLoc, NumVars), - Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} - - /// \brief Build an empty clause. - /// - /// \param NumVars Number of variables. - /// - explicit OMPLinearClause(unsigned NumVars) - : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(), - SourceLocation(), SourceLocation(), - NumVars), - Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {} - - /// \brief Gets the list of initial values for linear variables. - /// - /// There are NumVars expressions with initial values allocated after the - /// varlist, they are followed by NumVars update expressions (used to update - /// the linear variable's value on current iteration) and they are followed by - /// NumVars final expressions (used to calculate the linear variable's - /// value after the loop body). After these lists, there are 2 helper - /// expressions - linear step and a helper to calculate it before the - /// loop body (used when the linear step is not constant): - /// - /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[]; - /// Finals[]; Step; CalcStep; } - /// - MutableArrayRef<Expr *> getPrivates() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - MutableArrayRef<Expr *> getInits() { - return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); - } - ArrayRef<const Expr *> getInits() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); - } - - /// \brief Sets the list of update expressions for linear variables. - MutableArrayRef<Expr *> getUpdates() { - return MutableArrayRef<Expr *>(getInits().end(), varlist_size()); - } - ArrayRef<const Expr *> getUpdates() const { - return llvm::makeArrayRef(getInits().end(), varlist_size()); - } - - /// \brief Sets the list of final update expressions for linear variables. - MutableArrayRef<Expr *> getFinals() { - return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size()); - } - ArrayRef<const Expr *> getFinals() const { - return llvm::makeArrayRef(getUpdates().end(), varlist_size()); - } - - /// \brief Sets the list of the copies of original linear variables. - /// \param PL List of expressions. - void setPrivates(ArrayRef<Expr *> PL); - - /// \brief Sets the list of the initial values for linear variables. - /// \param IL List of expressions. - void setInits(ArrayRef<Expr *> IL); - -public: - /// \brief Creates clause with a list of variables \a VL and a linear step - /// \a Step. - /// - /// \param C AST Context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param Modifier Modifier of 'linear' clause. - /// \param ModifierLoc Modifier location. - /// \param ColonLoc Location of ':'. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param PL List of private copies of original variables. - /// \param IL List of initial values for the variables. - /// \param Step Linear step. - /// \param CalcStep Calculation of the linear step. - static OMPLinearClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, - ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep); - - /// \brief Creates an empty clause with the place for \a NumVars variables. - /// - /// \param C AST context. - /// \param NumVars Number of variables. - /// - static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars); - - /// \brief Set modifier. - void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; } - /// \brief Return modifier. - OpenMPLinearClauseKind getModifier() const { return Modifier; } - - /// \brief Set modifier location. - void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } - /// \brief Return modifier location. - SourceLocation getModifierLoc() const { return ModifierLoc; } - - /// \brief Sets the location of ':'. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Returns the location of ':'. - SourceLocation getColonLoc() const { return ColonLoc; } - - /// \brief Returns linear step. - Expr *getStep() { return *(getFinals().end()); } - /// \brief Returns linear step. - const Expr *getStep() const { return *(getFinals().end()); } - /// \brief Returns expression to calculate linear step. - Expr *getCalcStep() { return *(getFinals().end() + 1); } - /// \brief Returns expression to calculate linear step. - const Expr *getCalcStep() const { return *(getFinals().end() + 1); } - - /// \brief Sets the list of update expressions for linear variables. - /// \param UL List of expressions. - void setUpdates(ArrayRef<Expr *> UL); - - /// \brief Sets the list of final update expressions for linear variables. - /// \param FL List of expressions. - void setFinals(ArrayRef<Expr *> FL); - - typedef MutableArrayRef<Expr *>::iterator privates_iterator; - typedef ArrayRef<const Expr *>::iterator privates_const_iterator; - typedef llvm::iterator_range<privates_iterator> privates_range; - typedef llvm::iterator_range<privates_const_iterator> privates_const_range; - - privates_range privates() { - return privates_range(getPrivates().begin(), getPrivates().end()); - } - privates_const_range privates() const { - return privates_const_range(getPrivates().begin(), getPrivates().end()); - } - - typedef MutableArrayRef<Expr *>::iterator inits_iterator; - typedef ArrayRef<const Expr *>::iterator inits_const_iterator; - typedef llvm::iterator_range<inits_iterator> inits_range; - typedef llvm::iterator_range<inits_const_iterator> inits_const_range; - - inits_range inits() { - return inits_range(getInits().begin(), getInits().end()); - } - inits_const_range inits() const { - return inits_const_range(getInits().begin(), getInits().end()); - } - - typedef MutableArrayRef<Expr *>::iterator updates_iterator; - typedef ArrayRef<const Expr *>::iterator updates_const_iterator; - typedef llvm::iterator_range<updates_iterator> updates_range; - typedef llvm::iterator_range<updates_const_iterator> updates_const_range; - - updates_range updates() { - return updates_range(getUpdates().begin(), getUpdates().end()); - } - updates_const_range updates() const { - return updates_const_range(getUpdates().begin(), getUpdates().end()); - } - - typedef MutableArrayRef<Expr *>::iterator finals_iterator; - typedef ArrayRef<const Expr *>::iterator finals_const_iterator; - typedef llvm::iterator_range<finals_iterator> finals_range; - typedef llvm::iterator_range<finals_const_iterator> finals_const_range; - - finals_range finals() { - return finals_range(getFinals().begin(), getFinals().end()); - } - finals_const_range finals() const { - return finals_const_range(getFinals().begin(), getFinals().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_linear; - } -}; - -/// \brief This represents clause 'aligned' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp simd aligned(a,b : 8) -/// \endcode -/// In this example directive '#pragma omp simd' has clause 'aligned' -/// with variables 'a', 'b' and alignment '8'. -/// -class OMPAlignedClause final - : public OMPVarListClause<OMPAlignedClause>, - private llvm::TrailingObjects<OMPAlignedClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Location of ':'. - SourceLocation ColonLoc; - - /// \brief Sets the alignment for clause. - void setAlignment(Expr *A) { *varlist_end() = A; } - - /// \brief Build 'aligned' clause with given number of variables \a NumVars. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param ColonLoc Location of ':'. - /// \param EndLoc Ending location of the clause. - /// \param NumVars Number of variables. - /// - OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, - unsigned NumVars) - : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, StartLoc, LParenLoc, - EndLoc, NumVars), - ColonLoc(ColonLoc) {} - - /// \brief Build an empty clause. - /// - /// \param NumVars Number of variables. - /// - explicit OMPAlignedClause(unsigned NumVars) - : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(), - SourceLocation(), SourceLocation(), - NumVars), - ColonLoc(SourceLocation()) {} - -public: - /// \brief Creates clause with a list of variables \a VL and alignment \a A. - /// - /// \param C AST Context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param ColonLoc Location of ':'. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param A Alignment. - static OMPAlignedClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, - Expr *A); - - /// \brief Creates an empty clause with the place for \a NumVars variables. - /// - /// \param C AST context. - /// \param NumVars Number of variables. - /// - static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars); - - /// \brief Sets the location of ':'. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Returns the location of ':'. - SourceLocation getColonLoc() const { return ColonLoc; } - - /// \brief Returns alignment. - Expr *getAlignment() { return *varlist_end(); } - /// \brief Returns alignment. - const Expr *getAlignment() const { return *varlist_end(); } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_aligned; - } -}; - -/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives. -/// -/// \code -/// #pragma omp parallel copyin(a,b) -/// \endcode -/// In this example directive '#pragma omp parallel' has clause 'copyin' -/// with the variables 'a' and 'b'. -/// -class OMPCopyinClause final - : public OMPVarListClause<OMPCopyinClause>, - private llvm::TrailingObjects<OMPCopyinClause, Expr *> { - // Class has 3 additional tail allocated arrays: - // 1. List of helper expressions for proper generation of assignment operation - // required for copyin clause. This list represents sources. - // 2. List of helper expressions for proper generation of assignment operation - // required for copyin clause. This list represents destinations. - // 3. List of helper expressions that represents assignment operation: - // \code - // DstExprs = SrcExprs; - // \endcode - // Required for proper codegen of propagation of master's thread values of - // threadprivate variables to local instances of that variables in other - // implicit threads. - - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc, - EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPCopyinClause(unsigned N) - : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(), - SourceLocation(), SourceLocation(), - N) {} - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent source expression in the final - /// assignment statement performed by the copyin clause. - void setSourceExprs(ArrayRef<Expr *> SrcExprs); - - /// \brief Get the list of helper source expressions. - MutableArrayRef<Expr *> getSourceExprs() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent destination expression in the final - /// assignment statement performed by the copyin clause. - void setDestinationExprs(ArrayRef<Expr *> DstExprs); - - /// \brief Get the list of helper destination expressions. - MutableArrayRef<Expr *> getDestinationExprs() { - return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); - } - - /// \brief Set list of helper assignment expressions, required for proper - /// codegen of the clause. These expressions are assignment expressions that - /// assign source helper expressions to destination helper expressions - /// correspondingly. - void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - - /// \brief Get the list of helper assignment expressions. - MutableArrayRef<Expr *> getAssignmentOps() { - return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param SrcExprs List of helper expressions for proper generation of - /// assignment operation required for copyin clause. This list represents - /// sources. - /// \param DstExprs List of helper expressions for proper generation of - /// assignment operation required for copyin clause. This list represents - /// destinations. - /// \param AssignmentOps List of helper expressions that represents assignment - /// operation: - /// \code - /// DstExprs = SrcExprs; - /// \endcode - /// Required for proper codegen of propagation of master's thread values of - /// threadprivate variables to local instances of that variables in other - /// implicit threads. - /// - static OMPCopyinClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); - /// \brief Creates an empty clause with \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; - - helper_expr_const_range source_exprs() const { - return helper_expr_const_range(getSourceExprs().begin(), - getSourceExprs().end()); - } - helper_expr_range source_exprs() { - return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); - } - helper_expr_const_range destination_exprs() const { - return helper_expr_const_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_range destination_exprs() { - return helper_expr_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_const_range assignment_ops() const { - return helper_expr_const_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - helper_expr_range assignment_ops() { - return helper_expr_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_copyin; - } -}; - -/// \brief This represents clause 'copyprivate' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp single copyprivate(a,b) -/// \endcode -/// In this example directive '#pragma omp single' has clause 'copyprivate' -/// with the variables 'a' and 'b'. -/// -class OMPCopyprivateClause final - : public OMPVarListClause<OMPCopyprivateClause>, - private llvm::TrailingObjects<OMPCopyprivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc, - LParenLoc, EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPCopyprivateClause(unsigned N) - : OMPVarListClause<OMPCopyprivateClause>( - OMPC_copyprivate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent source expression in the final - /// assignment statement performed by the copyprivate clause. - void setSourceExprs(ArrayRef<Expr *> SrcExprs); - - /// \brief Get the list of helper source expressions. - MutableArrayRef<Expr *> getSourceExprs() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); - } - ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); - } - - /// \brief Set list of helper expressions, required for proper codegen of the - /// clause. These expressions represent destination expression in the final - /// assignment statement performed by the copyprivate clause. - void setDestinationExprs(ArrayRef<Expr *> DstExprs); - - /// \brief Get the list of helper destination expressions. - MutableArrayRef<Expr *> getDestinationExprs() { - return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); - } - - /// \brief Set list of helper assignment expressions, required for proper - /// codegen of the clause. These expressions are assignment expressions that - /// assign source helper expressions to destination helper expressions - /// correspondingly. - void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - - /// \brief Get the list of helper assignment expressions. - MutableArrayRef<Expr *> getAssignmentOps() { - return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); - } - ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); - } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param SrcExprs List of helper expressions for proper generation of - /// assignment operation required for copyprivate clause. This list represents - /// sources. - /// \param DstExprs List of helper expressions for proper generation of - /// assignment operation required for copyprivate clause. This list represents - /// destinations. - /// \param AssignmentOps List of helper expressions that represents assignment - /// operation: - /// \code - /// DstExprs = SrcExprs; - /// \endcode - /// Required for proper codegen of final assignment performed by the - /// copyprivate clause. - /// - static OMPCopyprivateClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); - /// \brief Creates an empty clause with \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; - - helper_expr_const_range source_exprs() const { - return helper_expr_const_range(getSourceExprs().begin(), - getSourceExprs().end()); - } - helper_expr_range source_exprs() { - return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); - } - helper_expr_const_range destination_exprs() const { - return helper_expr_const_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_range destination_exprs() { - return helper_expr_range(getDestinationExprs().begin(), - getDestinationExprs().end()); - } - helper_expr_const_range assignment_ops() const { - return helper_expr_const_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - helper_expr_range assignment_ops() { - return helper_expr_range(getAssignmentOps().begin(), - getAssignmentOps().end()); - } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_copyprivate; - } -}; - -/// \brief This represents implicit clause 'flush' for the '#pragma omp flush' -/// directive. -/// This clause does not exist by itself, it can be only as a part of 'omp -/// flush' directive. This clause is introduced to keep the original structure -/// of \a OMPExecutableDirective class and its derivatives and to use the -/// existing infrastructure of clauses with the list of variables. -/// -/// \code -/// #pragma omp flush(a,b) -/// \endcode -/// In this example directive '#pragma omp flush' has implicit clause 'flush' -/// with the variables 'a' and 'b'. -/// -class OMPFlushClause final - : public OMPVarListClause<OMPFlushClause>, - private llvm::TrailingObjects<OMPFlushClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc, - EndLoc, N) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPFlushClause(unsigned N) - : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(), - SourceLocation(), SourceLocation(), - N) {} - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// - static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N); - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_flush; - } -}; - -/// \brief This represents implicit clause 'depend' for the '#pragma omp task' -/// directive. -/// -/// \code -/// #pragma omp task depend(in:a,b) -/// \endcode -/// In this example directive '#pragma omp task' with clause 'depend' with the -/// variables 'a' and 'b' with dependency 'in'. -/// -class OMPDependClause final - : public OMPVarListClause<OMPDependClause>, - private llvm::TrailingObjects<OMPDependClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - /// \brief Dependency type (one of in, out, inout). - OpenMPDependClauseKind DepKind; - /// \brief Dependency type location. - SourceLocation DepLoc; - /// \brief Colon location. - SourceLocation ColonLoc; - /// \brief Build clause with number of variables \a N. - /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc, - EndLoc, N), - DepKind(OMPC_DEPEND_unknown) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPDependClause(unsigned N) - : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(), - SourceLocation(), SourceLocation(), - N), - DepKind(OMPC_DEPEND_unknown) {} - /// \brief Set dependency kind. - void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } - - /// \brief Set dependency kind and its location. - void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; } - - /// \brief Set colon location. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param DepKind Dependency type. - /// \param DepLoc Location of the dependency type. - /// \param ColonLoc Colon location. - /// \param VL List of references to the variables. - /// - static OMPDependClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N); - - /// \brief Get dependency type. - OpenMPDependClauseKind getDependencyKind() const { return DepKind; } - /// \brief Get dependency type location. - SourceLocation getDependencyLoc() const { return DepLoc; } - /// \brief Get colon location. - SourceLocation getColonLoc() const { return ColonLoc; } - - child_range children() { - return child_range(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_depend; - } -}; - -/// \brief This represents 'device' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp target device(a) -/// \endcode -/// In this example directive '#pragma omp target' has clause 'device' -/// with single expression 'a'. -/// -class OMPDeviceClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Device number. - Stmt *Device; - /// \brief Set the device number. - /// - /// \param E Device number. - /// - void setDevice(Expr *E) { Device = E; } - -public: - /// \brief Build 'device' clause. - /// - /// \param E Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc), - Device(E) {} - - /// \brief Build an empty clause. - /// - OMPDeviceClause() - : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Device(nullptr) {} - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return device number. - Expr *getDevice() { return cast<Expr>(Device); } - /// \brief Return device number. - Expr *getDevice() const { return cast<Expr>(Device); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_device; - } - - child_range children() { return child_range(&Device, &Device + 1); } -}; - -/// \brief This represents 'threads' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp ordered threads -/// \endcode -/// In this example directive '#pragma omp ordered' has simple 'threads' clause. -/// -class OMPThreadsClause : public OMPClause { -public: - /// \brief Build 'threads' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_threads, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPThreadsClause() - : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_threads; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'simd' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp ordered simd -/// \endcode -/// In this example directive '#pragma omp ordered' has simple 'simd' clause. -/// -class OMPSIMDClause : public OMPClause { -public: - /// \brief Build 'simd' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_simd, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_simd; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents clause 'map' in the '#pragma omp ...' -/// directives. -/// -/// \code -/// #pragma omp target map(a,b) -/// \endcode -/// In this example directive '#pragma omp target' has clause 'map' -/// with the variables 'a' and 'b'. -/// -class OMPMapClause final : public OMPVarListClause<OMPMapClause>, - private llvm::TrailingObjects<OMPMapClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; - friend class OMPClauseReader; - - /// \brief Map type modifier for the 'map' clause. - OpenMPMapClauseKind MapTypeModifier; - /// \brief Map type for the 'map' clause. - OpenMPMapClauseKind MapType; - /// \brief Location of the map type. - SourceLocation MapLoc; - /// \brief Colon location. - SourceLocation ColonLoc; - - /// \brief Set type modifier for the clause. - /// - /// \param T Type Modifier for the clause. - /// - void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; } - - /// \brief Set type for the clause. - /// - /// \param T Type for the clause. - /// - void setMapType(OpenMPMapClauseKind T) { MapType = T; } - - /// \brief Set type location. - /// - /// \param TLoc Type location. - /// - void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; } - - /// \brief Set colon location. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - - /// \brief Build clause with number of variables \a N. - /// - /// \param MapTypeModifier Map type modifier. - /// \param MapType Map type. - /// \param MapLoc Location of the map type. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier, - OpenMPMapClauseKind MapType, SourceLocation MapLoc, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPMapClause>(OMPC_map, StartLoc, LParenLoc, EndLoc, N), - MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {} - - /// \brief Build an empty clause. - /// - /// \param N Number of variables. - /// - explicit OMPMapClause(unsigned N) - : OMPVarListClause<OMPMapClause>(OMPC_map, SourceLocation(), - SourceLocation(), SourceLocation(), N), - MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {} - -public: - /// \brief Creates clause with a list of variables \a VL. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// \param TypeModifier Map type modifier. - /// \param Type Map type. - /// \param TypeLoc Location of the map type. - /// - static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, - OpenMPMapClauseKind TypeModifier, - OpenMPMapClauseKind Type, SourceLocation TypeLoc); - /// \brief Creates an empty clause with the place for \a N variables. - /// - /// \param C AST context. - /// \param N The number of variables. - /// - static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N); - - /// \brief Fetches mapping kind for the clause. - OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } - - /// \brief Fetches the map type modifier for the clause. - OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY { - return MapTypeModifier; - } - - /// \brief Fetches location of clause mapping kind. - SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; } - - /// \brief Get colon location. - SourceLocation getColonLoc() const { return ColonLoc; } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_map; - } - - child_range children() { - return child_range( - reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } -}; - -/// \brief This represents 'num_teams' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp teams num_teams(n) -/// \endcode -/// In this example directive '#pragma omp teams' has clause 'num_teams' -/// with single expression 'n'. -/// -class OMPNumTeamsClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief NumTeams number. - Stmt *NumTeams; - /// \brief Set the NumTeams number. - /// - /// \param E NumTeams number. - /// - void setNumTeams(Expr *E) { NumTeams = E; } - -public: - /// \brief Build 'num_teams' clause. - /// - /// \param E Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumTeams(E) {} - - /// \brief Build an empty clause. - /// - OMPNumTeamsClause() - : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumTeams(nullptr) {} - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return NumTeams number. - Expr *getNumTeams() { return cast<Expr>(NumTeams); } - /// \brief Return NumTeams number. - Expr *getNumTeams() const { return cast<Expr>(NumTeams); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_teams; - } - - child_range children() { return child_range(&NumTeams, &NumTeams + 1); } -}; - -/// \brief This represents 'thread_limit' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp teams thread_limit(n) -/// \endcode -/// In this example directive '#pragma omp teams' has clause 'thread_limit' -/// with single expression 'n'. -/// -class OMPThreadLimitClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief ThreadLimit number. - Stmt *ThreadLimit; - /// \brief Set the ThreadLimit number. - /// - /// \param E ThreadLimit number. - /// - void setThreadLimit(Expr *E) { ThreadLimit = E; } - -public: - /// \brief Build 'thread_limit' clause. - /// - /// \param E Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPThreadLimitClause(Expr *E, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc), - ThreadLimit(E) {} - - /// \brief Build an empty clause. - /// - OMPThreadLimitClause() - : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), ThreadLimit(nullptr) {} - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return ThreadLimit number. - Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); } - /// \brief Return ThreadLimit number. - Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_thread_limit; - } - - child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); } -}; - -/// \brief This represents 'priority' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp task priority(n) -/// \endcode -/// In this example directive '#pragma omp teams' has clause 'priority' with -/// single expression 'n'. -/// -class OMPPriorityClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Priority number. - Stmt *Priority; - /// \brief Set the Priority number. - /// - /// \param E Priority number. - /// - void setPriority(Expr *E) { Priority = E; } - -public: - /// \brief Build 'priority' clause. - /// - /// \param E Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc), - Priority(E) {} - - /// \brief Build an empty clause. - /// - OMPPriorityClause() - : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Priority(nullptr) {} - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return Priority number. - Expr *getPriority() { return cast<Expr>(Priority); } - /// \brief Return Priority number. - Expr *getPriority() const { return cast<Expr>(Priority); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_priority; - } - - child_range children() { return child_range(&Priority, &Priority + 1); } -}; - -/// \brief This represents 'grainsize' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp taskloop grainsize(4) -/// \endcode -/// In this example directive '#pragma omp taskloop' has clause 'grainsize' -/// with single expression '4'. -/// -class OMPGrainsizeClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Safe iteration space distance. - Stmt *Grainsize; - - /// \brief Set safelen. - void setGrainsize(Expr *Size) { Grainsize = Size; } - -public: - /// \brief Build 'grainsize' clause. - /// - /// \param Size Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc), - Grainsize(Size) {} - - /// \brief Build an empty clause. - /// - explicit OMPGrainsizeClause() - : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Grainsize(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return safe iteration space distance. - Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_grainsize; - } - - child_range children() { return child_range(&Grainsize, &Grainsize + 1); } -}; - -/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp taskloop nogroup -/// \endcode -/// In this example directive '#pragma omp taskloop' has 'nogroup' clause. -/// -class OMPNogroupClause : public OMPClause { -public: - /// \brief Build 'nogroup' clause. - /// - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {} - - /// \brief Build an empty clause. - /// - OMPNogroupClause() - : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {} - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nogroup; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This represents 'num_tasks' clause in the '#pragma omp ...' -/// directive. -/// -/// \code -/// #pragma omp taskloop num_tasks(4) -/// \endcode -/// In this example directive '#pragma omp taskloop' has clause 'num_tasks' -/// with single expression '4'. -/// -class OMPNumTasksClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Safe iteration space distance. - Stmt *NumTasks; - - /// \brief Set safelen. - void setNumTasks(Expr *Size) { NumTasks = Size; } - -public: - /// \brief Build 'num_tasks' clause. - /// - /// \param Size Expression associated with this clause. - /// \param StartLoc Starting location of the clause. - /// \param EndLoc Ending location of the clause. - /// - OMPNumTasksClause(Expr *Size, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumTasks(Size) {} - - /// \brief Build an empty clause. - /// - explicit OMPNumTasksClause() - : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumTasks(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Return safe iteration space distance. - Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_tasks; - } - - child_range children() { return child_range(&NumTasks, &NumTasks + 1); } -}; - -/// \brief This represents 'hint' clause in the '#pragma omp ...' directive. -/// -/// \code -/// #pragma omp critical (name) hint(6) -/// \endcode -/// In this example directive '#pragma omp critical' has name 'name' and clause -/// 'hint' with argument '6'. -/// -class OMPHintClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Hint expression of the 'hint' clause. - Stmt *Hint; - - /// \brief Set hint expression. - /// - void setHint(Expr *H) { Hint = H; } - -public: - /// \brief Build 'hint' clause with expression \a Hint. - /// - /// \param Hint Hint expression. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// - OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc), - Hint(Hint) {} - - /// \brief Build an empty clause. - /// - OMPHintClause() - : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Hint(nullptr) {} - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Returns number of threads. - Expr *getHint() const { return cast_or_null<Expr>(Hint); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_hint; - } - - child_range children() { return child_range(&Hint, &Hint + 1); } -}; - -} // end namespace clang - -#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h deleted file mode 100644 index 2235c10..0000000 --- a/include/clang/AST/OperationKinds.h +++ /dev/null @@ -1,356 +0,0 @@ -//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file enumerates the different kinds of operations that can be -// performed by various expressions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_OPERATIONKINDS_H -#define LLVM_CLANG_AST_OPERATIONKINDS_H - -namespace clang { - -/// CastKind - The kind of operation required for a conversion. -enum CastKind { - /// 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 - 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. A conversion - /// from any pointer type to a C pointer type is a bitcast unless - /// it's actually BaseToDerived or DerivedToBase. A conversion to a - /// block pointer or ObjC pointer type is a bitcast only if the - /// operand has the same type kind; otherwise, it's one of the - /// specialized casts below. - /// - /// Vector coercions are bitcasts. - CK_BitCast, - - /// 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_NoOp - A conversion which does not affect the type other than - /// (possibly) adding qualifiers. - /// int -> int - /// char** -> const char * const * - CK_NoOp, - - /// 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 - A conversion from a C++ class pointer - /// to a base class pointer. - /// A *a = new B(); - CK_DerivedToBase, - - /// 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 - A C++ dynamic_cast. - CK_Dynamic, - - /// 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. - /// void(int) -> void(*)(int) - CK_FunctionToPointerDecay, - - /// 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_ReinterpretMemberPointer - Reinterpret a member pointer as a - /// different kind of member pointer. C++ forbids this from - /// crossing between function and object types, but otherwise does - /// not restrict it. However, the only operation that is permitted - /// on a "punned" member pointer is casting it back to the original - /// type, which is required to be a lossless operation (although - /// many ABIs do not guarantee this on all possible intermediate types). - CK_ReinterpretMemberPointer, - - /// 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. - /// struct A { A(int); }; A a = A(10); - CK_ConstructorConversion, - - /// 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. 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, discarding the computed value. - /// (void) malloc(2048) - CK_ToVoid, - - /// 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 - 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. 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_CPointerToObjCPointerCast - Casting a C pointer kind to an - /// Objective-C pointer. - CK_CPointerToObjCPointerCast, - - /// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an - /// ObjC pointer. - CK_BlockPointerToObjCPointerCast, - - /// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer - /// to a block pointer. Block-to-block casts are bitcasts. - CK_AnyPointerToBlockPointerCast, - - /// \brief Converting between two Objective-C object types, which - /// can occur when performing reference binding to an Objective-C - /// object. - 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, - - /// \brief [ARC] Produces a retainable object pointer so that it may - /// be consumed, e.g. by being passed to a consuming parameter. - /// Calls objc_retain. - CK_ARCProduceObject, - - /// \brief [ARC] Consumes a retainable object pointer that has just - /// been produced, e.g. as the return value of a retaining call. - /// Enters a cleanup to call objc_release at some indefinite time. - CK_ARCConsumeObject, - - /// \brief [ARC] Reclaim a retainable object pointer object that may - /// have been produced and autoreleased as part of a function return - /// sequence. - CK_ARCReclaimReturnedObject, - - /// \brief [ARC] Causes a value of block type to be copied to the - /// heap, if it is not already there. A number of other operations - /// in ARC cause blocks to be copied; this is for cases where that - /// would not otherwise be guaranteed, such as when casting to a - /// non-block pointer type. - CK_ARCExtendBlockObject, - - /// \brief Converts from _Atomic(T) to T. - CK_AtomicToNonAtomic, - /// \brief Converts from T to _Atomic(T). - CK_NonAtomicToAtomic, - - /// \brief Causes a block literal to by copied to the heap and then - /// autoreleased. - /// - /// This particular cast kind is used for the conversion from a C++11 - /// lambda expression to a block pointer. - CK_CopyAndAutoreleaseBlockObject, - - // Convert a builtin function to a function pointer; only allowed in the - // callee of a call expression. - CK_BuiltinFnToFnPtr, - - // Convert a zero value for OpenCL event_t initialization. - CK_ZeroToOCLEvent, - - // Convert a pointer to a different address space. - CK_AddressSpaceConversion -}; - -static const CastKind CK_Invalid = static_cast<CastKind>(-1); - -enum BinaryOperatorKind { - // Operators listed in order of precedence. - // Note that additions to this should also update the StmtVisitor class. - BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. - BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. - BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. - BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. - BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. - BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. - BO_And, // [C99 6.5.10] Bitwise AND operator. - BO_Xor, // [C99 6.5.11] Bitwise XOR operator. - BO_Or, // [C99 6.5.12] Bitwise OR operator. - BO_LAnd, // [C99 6.5.13] Logical AND operator. - BO_LOr, // [C99 6.5.14] Logical OR operator. - BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. - BO_DivAssign, BO_RemAssign, - BO_AddAssign, BO_SubAssign, - BO_ShlAssign, BO_ShrAssign, - BO_AndAssign, BO_XorAssign, - BO_OrAssign, - BO_Comma // [C99 6.5.17] Comma operator. -}; - -enum UnaryOperatorKind { - // Note that additions to this should also update the StmtVisitor class. - UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement - UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement - UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection - UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic - UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic - UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension. - UO_Extension, // __extension__ marker. - UO_Coawait // [C++ Coroutines] co_await operator -}; - -/// \brief The kind of bridging performed by the Objective-C bridge cast. -enum ObjCBridgeCastKind { - /// \brief Bridging via __bridge, which does nothing but reinterpret - /// the bits. - OBC_Bridge, - /// \brief Bridging via __bridge_transfer, which transfers ownership of an - /// Objective-C pointer into ARC. - OBC_BridgeTransfer, - /// \brief Bridging via __bridge_retain, which makes an ARC object available - /// as a +1 C pointer. - OBC_BridgeRetained -}; - -} - -#endif diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h deleted file mode 100644 index 8945c41..0000000 --- a/include/clang/AST/ParentMap.h +++ /dev/null @@ -1,67 +0,0 @@ -//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- 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 ParentMap class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_PARENTMAP_H -#define LLVM_CLANG_AST_PARENTMAP_H - -namespace clang { -class Stmt; -class Expr; - -class ParentMap { - void* Impl; -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); - - /// Manually sets the parent of \p S to \p Parent. - /// - /// If \p S is already in the map, this method will update the mapping. - void setParent(const Stmt *S, const Stmt *Parent); - - Stmt *getParent(Stmt*) const; - Stmt *getParentIgnoreParens(Stmt *) const; - Stmt *getParentIgnoreParenCasts(Stmt *) const; - Stmt *getParentIgnoreParenImpCasts(Stmt *) const; - Stmt *getOuterParenParent(Stmt *) const; - - const Stmt *getParent(const Stmt* S) const { - return getParent(const_cast<Stmt*>(S)); - } - - const Stmt *getParentIgnoreParens(const Stmt *S) const { - return getParentIgnoreParens(const_cast<Stmt*>(S)); - } - - const Stmt *getParentIgnoreParenCasts(const Stmt *S) const { - return getParentIgnoreParenCasts(const_cast<Stmt*>(S)); - } - - bool hasParent(Stmt* S) const { - return getParent(S) != nullptr; - } - - bool isConsumedExpr(Expr *E) const; - - bool isConsumedExpr(const Expr *E) const { - return isConsumedExpr(const_cast<Expr*>(E)); - } -}; - -} // end clang namespace -#endif diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h deleted file mode 100644 index 8ab3f617..0000000 --- a/include/clang/AST/PrettyPrinter.h +++ /dev/null @@ -1,175 +0,0 @@ -//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- 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 PrinterHelper interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_PRETTYPRINTER_H -#define LLVM_CLANG_AST_PRETTYPRINTER_H - -#include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" - -namespace clang { - -class LangOptions; -class SourceManager; -class Stmt; -class TagDecl; - -class PrinterHelper { -public: - virtual ~PrinterHelper(); - virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0; -}; - -/// \brief Describes how types, statements, expressions, and -/// declarations should be printed. -struct PrintingPolicy { - /// \brief Create a default printing policy for C. - PrintingPolicy(const LangOptions &LO) - : LangOpts(LO), Indentation(2), SuppressSpecifiers(false), - SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), - SuppressUnwrittenScope(false), SuppressInitializers(false), - ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), - SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), - Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), - Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), - IncludeNewlines(true), MSVCFormatting(false) { } - - /// \brief What language we're printing. - LangOptions LangOpts; - - /// \brief The number of spaces to use to indent each line. - unsigned Indentation : 8; - - /// \brief Whether we should suppress printing of the actual specifiers for - /// the given type or declaration. - /// - /// This flag is only used when we are printing declarators beyond - /// the first declarator within a declaration group. For example, given: - /// - /// \code - /// const int *x, *y; - /// \endcode - /// - /// SuppressSpecifiers will be false when printing the - /// declaration for "x", so that we will print "int *x"; it will be - /// \c true when we print "y", so that we suppress printing the - /// "const int" type specifier and instead only print the "*y". - bool SuppressSpecifiers : 1; - - /// \brief Whether type printing should skip printing the tag keyword. - /// - /// This is used when printing the inner type of elaborated types, - /// (as the tag keyword is part of the elaborated type): - /// - /// \code - /// struct Geometry::Point; - /// \endcode - bool SuppressTagKeyword : 1; - - /// \brief Whether type printing should skip printing the actual tag type. - /// - /// This is used when the caller needs to print a tag definition in front - /// of the type, as in constructs like the following: - /// - /// \code - /// typedef struct { int x, y; } Point; - /// \endcode - bool SuppressTag : 1; - - /// \brief Suppresses printing of scope specifiers. - bool SuppressScope : 1; - - /// \brief Suppress printing parts of scope specifiers that don't need - /// to be written, e.g., for inline or anonymous namespaces. - bool SuppressUnwrittenScope : 1; - - /// \brief Suppress printing of variable initializers. - /// - /// This flag is used when printing the loop variable in a for-range - /// statement. For example, given: - /// - /// \code - /// for (auto x : coll) - /// \endcode - /// - /// SuppressInitializers will be true when printing "auto x", so that the - /// internal initializer constructed for x will not be printed. - bool SuppressInitializers : 1; - - /// \brief Whether we should print the sizes of constant array expressions - /// as written in the sources. - /// - /// This flag determines whether array types declared as - /// - /// \code - /// int a[4+10*10]; - /// char a[] = "A string"; - /// \endcode - /// - /// will be printed as written or as follows: - /// - /// \code - /// int a[104]; - /// char a[9] = "A string"; - /// \endcode - bool ConstantArraySizeAsWritten : 1; - - /// \brief When printing an anonymous tag name, also print the location of - /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just - /// prints "(anonymous)" for the name. - bool AnonymousTagLocations : 1; - - /// \brief When true, suppress printing of the __strong lifetime qualifier in - /// ARC. - unsigned SuppressStrongLifetime : 1; - - /// \brief When true, suppress printing of lifetime qualifier in - /// ARC. - unsigned SuppressLifetimeQualifiers : 1; - - /// \brief Whether we can use 'bool' rather than '_Bool', even if the language - /// doesn't actually have 'bool' (because, e.g., it is defined as a macro). - unsigned Bool : 1; - - /// \brief Provide a 'terse' output. - /// - /// For example, in this mode we don't print function bodies, class members, - /// declarations inside namespaces etc. Effectively, this should print - /// only the requested declaration. - unsigned TerseOutput : 1; - - /// \brief When true, do certain refinement needed for producing proper - /// declaration tag; such as, do not print attributes attached to the declaration. - /// - unsigned PolishForDeclaration : 1; - - /// \brief When true, print the half-precision floating-point type as 'half' - /// instead of '__fp16' - unsigned Half : 1; - - /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in - /// Microsoft mode when wchar_t is not available. - unsigned MSWChar : 1; - - /// \brief When true, include newlines after statements like "break", etc. - unsigned IncludeNewlines : 1; - - /// \brief Use whitespace and punctuation like MSVC does. In particular, this - /// prints anonymous namespaces as `anonymous namespace' and does not insert - /// spaces after template arguments. - bool MSVCFormatting : 1; -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h deleted file mode 100644 index 2e005dd..0000000 --- a/include/clang/AST/RawCommentList.h +++ /dev/null @@ -1,203 +0,0 @@ -//===--- RawCommentList.h - Classes for processing raw comments -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_RAWCOMMENTLIST_H -#define LLVM_CLANG_AST_RAWCOMMENTLIST_H - -#include "clang/Basic/CommentOptions.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/ArrayRef.h" - -namespace clang { - -class ASTContext; -class ASTReader; -class Decl; -class Preprocessor; - -namespace comments { - class FullComment; -} // end namespace comments - -class RawComment { -public: - enum CommentKind { - RCK_Invalid, ///< Invalid comment - RCK_OrdinaryBCPL, ///< Any normal BCPL comments - RCK_OrdinaryC, ///< Any normal C comment - RCK_BCPLSlash, ///< \code /// stuff \endcode - RCK_BCPLExcl, ///< \code //! stuff \endcode - RCK_JavaDoc, ///< \code /** stuff */ \endcode - RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc - RCK_Merged ///< Two or more documentation comments merged together - }; - - RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { } - - RawComment(const SourceManager &SourceMgr, SourceRange SR, - bool Merged, bool ParseAllComments); - - CommentKind getKind() const LLVM_READONLY { - return (CommentKind) Kind; - } - - bool isInvalid() const LLVM_READONLY { - return Kind == RCK_Invalid; - } - - bool isMerged() const LLVM_READONLY { - return Kind == RCK_Merged; - } - - /// Is this comment attached to any declaration? - bool isAttached() const LLVM_READONLY { - return IsAttached; - } - - void setAttached() { - IsAttached = true; - } - - /// Returns true if it is a comment that should be put after a member: - /// \code ///< stuff \endcode - /// \code //!< stuff \endcode - /// \code /**< stuff */ \endcode - /// \code /*!< stuff */ \endcode - bool isTrailingComment() const LLVM_READONLY { - assert(isDocumentation()); - return IsTrailingComment; - } - - /// Returns true if it is a probable typo: - /// \code //< stuff \endcode - /// \code /*< stuff */ \endcode - bool isAlmostTrailingComment() const LLVM_READONLY { - return IsAlmostTrailingComment; - } - - /// Returns true if this comment is not a documentation comment. - bool isOrdinary() const LLVM_READONLY { - return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) && - !ParseAllComments; - } - - /// Returns true if this comment any kind of a documentation comment. - bool isDocumentation() const LLVM_READONLY { - return !isInvalid() && !isOrdinary(); - } - - /// Returns whether we are parsing all comments. - bool isParseAllComments() const LLVM_READONLY { - return ParseAllComments; - } - - /// Returns raw comment text with comment markers. - StringRef getRawText(const SourceManager &SourceMgr) const { - if (RawTextValid) - return RawText; - - RawText = getRawTextSlow(SourceMgr); - RawTextValid = true; - return RawText; - } - - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - - const char *getBriefText(const ASTContext &Context) const { - if (BriefTextValid) - return BriefText; - - return extractBriefText(Context); - } - - /// Parse the comment, assuming it is attached to decl \c D. - comments::FullComment *parse(const ASTContext &Context, - const Preprocessor *PP, const Decl *D) const; - -private: - SourceRange Range; - - mutable StringRef RawText; - mutable const char *BriefText; - - mutable bool RawTextValid : 1; ///< True if RawText is valid - mutable bool BriefTextValid : 1; ///< True if BriefText is valid - - unsigned Kind : 3; - - /// True if comment is attached to a declaration in ASTContext. - bool IsAttached : 1; - - bool IsTrailingComment : 1; - bool IsAlmostTrailingComment : 1; - - /// When true, ordinary comments starting with "//" and "/*" will be - /// considered as documentation comments. - bool ParseAllComments : 1; - - /// \brief Constructor for AST deserialization. - RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, - bool IsAlmostTrailingComment, - bool ParseAllComments) : - Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), - IsAttached(false), IsTrailingComment(IsTrailingComment), - IsAlmostTrailingComment(IsAlmostTrailingComment), - ParseAllComments(ParseAllComments) - { } - - StringRef getRawTextSlow(const SourceManager &SourceMgr) const; - - const char *extractBriefText(const ASTContext &Context) const; - - friend class ASTReader; -}; - -/// \brief Compare comments' source locations. -template<> -class BeforeThanCompare<RawComment> { - const SourceManager &SM; - -public: - explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } - - bool operator()(const RawComment &LHS, const RawComment &RHS) { - return SM.isBeforeInTranslationUnit(LHS.getLocStart(), RHS.getLocStart()); - } - - bool operator()(const RawComment *LHS, const RawComment *RHS) { - return operator()(*LHS, *RHS); - } -}; - -/// \brief This class represents all comments included in the translation unit, -/// sorted in order of appearance in the translation unit. -class RawCommentList { -public: - RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} - - void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator); - - ArrayRef<RawComment *> getComments() const { - return Comments; - } - -private: - SourceManager &SourceMgr; - std::vector<RawComment *> Comments; - - void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments); - - friend class ASTReader; -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h deleted file mode 100644 index 667f235..0000000 --- a/include/clang/AST/RecordLayout.h +++ /dev/null @@ -1,315 +0,0 @@ -//===--- RecordLayout.h - Layout information for a struct/union -*- 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 RecordLayout interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H -#define LLVM_CLANG_AST_RECORDLAYOUT_H - -#include "clang/AST/CharUnits.h" -#include "clang/AST/DeclCXX.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { - class ASTContext; - class FieldDecl; - class RecordDecl; - class CXXRecordDecl; - -/// ASTRecordLayout - -/// This class contains layout information for one RecordDecl, -/// which is a struct/union/class. The decl represented must be a definition, -/// not a forward declaration. -/// This class is also used to contain layout information for one -/// ObjCInterfaceDecl. FIXME - Find appropriate name. -/// These objects are managed by ASTContext. -class ASTRecordLayout { -public: - struct VBaseInfo { - /// The offset to this virtual base in the complete-object layout - /// of this class. - CharUnits VBaseOffset; - - private: - /// Whether this virtual base requires a vtordisp field in the - /// Microsoft ABI. These fields are required for certain operations - /// in constructors and destructors. - bool HasVtorDisp; - - public: - bool hasVtorDisp() const { return HasVtorDisp; } - - VBaseInfo() : HasVtorDisp(false) {} - - VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) : - VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} - }; - - typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo> - VBaseOffsetsMapTy; - -private: - /// Size - Size of record in characters. - CharUnits Size; - - /// DataSize - Size of record in characters without tail padding. - CharUnits DataSize; - - // Alignment - Alignment of record in characters. - CharUnits Alignment; - - /// RequiredAlignment - The required alignment of the object. In the MS-ABI - /// the __declspec(align()) trumps #pramga pack and must always be obeyed. - CharUnits RequiredAlignment; - - /// FieldOffsets - Array of field offsets in bits. - uint64_t *FieldOffsets; - - // FieldCount - Number of fields. - unsigned FieldCount; - - /// CXXRecordLayoutInfo - Contains C++ specific layout information. - struct CXXRecordLayoutInfo { - /// NonVirtualSize - The non-virtual size (in chars) of an object, which is - /// the size of the object without virtual bases. - CharUnits NonVirtualSize; - - /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, - /// which is the alignment of the object without virtual bases. - CharUnits NonVirtualAlignment; - - /// 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. - CharUnits SizeOfLargestEmptySubobject; - - /// VBPtrOffset - Virtual base table offset (Microsoft-only). - CharUnits VBPtrOffset; - - /// HasOwnVFPtr - Does this class provide a virtual function table - /// (vtable in Itanium, vftbl in Microsoft) that is independent from - /// its base classes? - bool HasOwnVFPtr : 1; - - /// HasVFPtr - Does this class have a vftable that could be extended by - /// a derived class. The class may have inherited this pointer from - /// a primary base class. - bool HasExtendableVFPtr : 1; - - /// HasZeroSizedSubObject - True if this class contains a zero sized member - /// or base or a base with a zero sized member or base. Only used for - /// MS-ABI. - bool HasZeroSizedSubObject : 1; - - /// \brief True if this class is zero sized or first base is zero sized or - /// has this property. Only used for MS-ABI. - bool LeadsWithZeroSizedBase : 1; - - /// PrimaryBase - The primary base info for this record. - llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; - - /// BaseSharingVBPtr - The base we share vbptr with. - const CXXRecordDecl *BaseSharingVBPtr; - - /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) - typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; - - /// BaseOffsets - Contains a map from base classes to their offset. - BaseOffsetsMapTy BaseOffsets; - - /// VBaseOffsets - Contains a map from vbase classes to their offset. - VBaseOffsetsMapTy VBaseOffsets; - }; - - /// CXXInfo - If the record layout is for a C++ record, this will have - /// C++ specific information about the record. - CXXRecordLayoutInfo *CXXInfo; - - friend class ASTContext; - - ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - CharUnits requiredAlignment, - CharUnits datasize, const uint64_t *fieldoffsets, - unsigned fieldcount); - - // Constructor for C++ records. - typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; - ASTRecordLayout(const ASTContext &Ctx, - CharUnits size, CharUnits alignment, - CharUnits requiredAlignment, - bool hasOwnVFPtr, bool hasExtendableVFPtr, - CharUnits vbptroffset, - CharUnits datasize, - const uint64_t *fieldoffsets, unsigned fieldcount, - CharUnits nonvirtualsize, CharUnits nonvirtualalignment, - CharUnits SizeOfLargestEmptySubobject, - const CXXRecordDecl *PrimaryBase, - bool IsPrimaryBaseVirtual, - const CXXRecordDecl *BaseSharingVBPtr, - bool HasZeroSizedSubObject, - bool LeadsWithZeroSizedBase, - const BaseOffsetsMapTy& BaseOffsets, - const VBaseOffsetsMapTy& VBaseOffsets); - - ~ASTRecordLayout() = default; - - void Destroy(ASTContext &Ctx); - - ASTRecordLayout(const ASTRecordLayout &) = delete; - void operator=(const ASTRecordLayout &) = delete; -public: - - /// getAlignment - Get the record alignment in characters. - CharUnits getAlignment() const { return Alignment; } - - /// 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; } - - /// getFieldOffset - Get the offset of the given field index, in - /// bits. - uint64_t getFieldOffset(unsigned FieldNo) const { - assert (FieldNo < FieldCount && "Invalid Field No"); - return FieldOffsets[FieldNo]; - } - - /// getDataSize() - Get the record data size, which is the record size - /// without tail padding, in characters. - CharUnits getDataSize() const { - return DataSize; - } - - /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, - /// which is the size of the object without virtual bases. - CharUnits getNonVirtualSize() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return CXXInfo->NonVirtualSize; - } - - /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, - /// which is the alignment of the object without virtual bases. - CharUnits getNonVirtualAlignment() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return CXXInfo->NonVirtualAlignment; - } - - /// 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.getPointer(); - } - - /// 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!"); - - return CXXInfo->PrimaryBase.getInt(); - } - - /// 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 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].VBaseOffset; - } - - CharUnits getSizeOfLargestEmptySubobject() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->SizeOfLargestEmptySubobject; - } - - /// hasOwnVFPtr - Does this class provide its own virtual-function - /// table pointer, rather than inheriting one from a primary base - /// class? If so, it is at offset zero. - /// - /// This implies that the ABI has no primary base class, meaning - /// that it has no base classes that are suitable under the conditions - /// of the ABI. - bool hasOwnVFPtr() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->HasOwnVFPtr; - } - - /// hasVFPtr - Does this class have a virtual function table pointer - /// that can be extended by a derived class? This is synonymous with - /// this class having a VFPtr at offset zero. - bool hasExtendableVFPtr() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->HasExtendableVFPtr; - } - - /// hasOwnVBPtr - Does this class provide its own virtual-base - /// table pointer, rather than inheriting one from a primary base - /// class? - /// - /// This implies that the ABI has no primary base class, meaning - /// that it has no base classes that are suitable under the conditions - /// of the ABI. - bool hasOwnVBPtr() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return hasVBPtr() && !CXXInfo->BaseSharingVBPtr; - } - - /// hasVBPtr - Does this class have a virtual function table pointer. - bool hasVBPtr() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return !CXXInfo->VBPtrOffset.isNegative(); - } - - CharUnits getRequiredAlignment() const { - return RequiredAlignment; - } - - bool hasZeroSizedSubObject() const { - return CXXInfo && CXXInfo->HasZeroSizedSubObject; - } - - bool leadsWithZeroSizedBase() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->LeadsWithZeroSizedBase; - } - - /// getVBPtrOffset - Get the offset for virtual base table pointer. - /// This is only meaningful with the Microsoft ABI. - CharUnits getVBPtrOffset() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->VBPtrOffset; - } - - const CXXRecordDecl *getBaseSharingVBPtr() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->BaseSharingVBPtr; - } - - const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->VBaseOffsets; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h deleted file mode 100644 index e6f7583..0000000 --- a/include/clang/AST/RecursiveASTVisitor.h +++ /dev/null @@ -1,2805 +0,0 @@ -//===--- RecursiveASTVisitor.h - Recursive AST 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 RecursiveASTVisitor interface, which recursively -// traverses the entire AST. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H -#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H - -#include <type_traits> - -#include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLoc.h" - -// The following three macros are used for meta programming. The code -// using them is responsible for defining macro OPERATOR(). - -// All unary operators. -#define UNARYOP_LIST() \ - OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ - OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ - OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) OPERATOR(Coawait) - -// All binary operators (excluding compound assign operators). -#define BINOP_LIST() \ - OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ - OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ - OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ - OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \ - OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) - -// All compound assign operators. -#define CAO_LIST() \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) - -namespace clang { - -// A helper macro to implement short-circuiting when recursing. It -// invokes CALL_EXPR, which must be a method call, on the derived -// object (s.t. a user of RecursiveASTVisitor can override the method -// in CALL_EXPR). -#define TRY_TO(CALL_EXPR) \ - do { \ - if (!getDerived().CALL_EXPR) \ - return false; \ - } while (0) - -/// \brief A class that does preorder depth-first traversal on the -/// entire Clang AST and visits each node. -/// -/// This class performs three distinct tasks: -/// 1. traverse the AST (i.e. go to each node); -/// 2. at a given node, walk up the class hierarchy, starting from -/// the node's dynamic type, until the top-most class (e.g. Stmt, -/// Decl, or Type) is reached. -/// 3. given a (node, class) combination, where 'class' is some base -/// class of the dynamic type of 'node', call a user-overridable -/// function to actually visit the node. -/// -/// These tasks are done by three groups of methods, respectively: -/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point -/// for traversing an AST rooted at x. This method simply -/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo -/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and -/// then recursively visits the child nodes of x. -/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work -/// similarly. -/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit -/// any child node of x. Instead, it first calls WalkUpFromBar(x) -/// where Bar is the direct parent class of Foo (unless Foo has -/// no parent), and then calls VisitFoo(x) (see the next list item). -/// 3. VisitFoo(Foo *x) does task #3. -/// -/// These three method groups are tiered (Traverse* > WalkUpFrom* > -/// Visit*). A method (e.g. Traverse*) may call methods from the same -/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). -/// It may not call methods from a higher tier. -/// -/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar -/// is Foo's super class) before calling VisitFoo(), the result is -/// that the Visit*() methods for a given node are called in the -/// top-down order (e.g. for a node of type NamespaceDecl, the order will -/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). -/// -/// This scheme guarantees that all Visit*() calls for the same AST -/// node are grouped together. In other words, Visit*() methods for -/// different nodes are never interleaved. -/// -/// Clients of this visitor should subclass the visitor (providing -/// themselves as the template argument, using the curiously recurring -/// template pattern) and override any of the Traverse*, WalkUpFrom*, -/// and Visit* methods for declarations, types, statements, -/// expressions, or other AST nodes where the visitor should customize -/// behavior. Most users only need to override Visit*. Advanced -/// users may override Traverse* and WalkUpFrom* to implement custom -/// traversal strategies. Returning false from one of these overridden -/// functions will abort the entire traversal. -/// -/// By default, this visitor tries to visit every part of the explicit -/// source code exactly once. The default policy towards templates -/// is to descend into the 'pattern' class or function body, not any -/// explicit or implicit instantiations. Explicit specializations -/// are still visited, and the patterns of partial specializations -/// are visited separately. This behavior can be changed by -/// overriding shouldVisitTemplateInstantiations() in the derived class -/// to return true, in which case all known implicit and explicit -/// instantiations will be visited at the same time as the pattern -/// from which they were produced. -template <typename Derived> class RecursiveASTVisitor { -public: - /// A queue used for performing data recursion over statements. - /// Parameters involving this type are used to implement data - /// recursion over Stmts and Exprs within this class, and should - /// typically not be explicitly specified by derived classes. - typedef SmallVectorImpl<Stmt *> DataRecursionQueue; - - /// \brief Return a reference to the derived class. - Derived &getDerived() { return *static_cast<Derived *>(this); } - - /// \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 Return whether this visitor should recurse into implicit - /// code, e.g., implicit constructors and destructors. - bool shouldVisitImplicitCode() const { return false; } - - /// \brief Recursively visit a statement or expression, by - /// dispatching to Traverse*() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is nullptr). - bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); - - /// \brief Recursively visit a type, by dispatching to - /// Traverse*Type() based on the argument's getTypeClass() property. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type). - bool TraverseType(QualType T); - - /// \brief Recursively visit a type with location, by dispatching to - /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type location). - bool TraverseTypeLoc(TypeLoc TL); - - /// \brief Recursively visit an attribute, by dispatching to - /// Traverse*Attr() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type location). - bool TraverseAttr(Attr *At); - - /// \brief Recursively visit a declaration, by dispatching to - /// Traverse*Decl() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is NULL). - bool TraverseDecl(Decl *D); - - /// \brief Recursively visit a C++ nested-name-specifier. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - - /// \brief Recursively visit a C++ nested-name-specifier with location - /// information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - - /// \brief Recursively visit a name with its location information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); - - /// \brief Recursively visit a template name and dispatch to the - /// appropriate method. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseTemplateName(TemplateName Template); - - /// \brief Recursively visit a template argument and dispatch to the - /// appropriate method for the argument type. - /// - /// \returns false if the visitation was terminated early, true otherwise. - // FIXME: migrate callers to TemplateArgumentLoc instead. - bool TraverseTemplateArgument(const TemplateArgument &Arg); - - /// \brief Recursively visit a template argument location and dispatch to the - /// appropriate method for the argument type. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); - - /// \brief Recursively visit a set of template arguments. - /// This can be overridden by a subclass, but it's not expected that - /// will be needed -- this visitor always dispatches to another. - /// - /// \returns false if the visitation was terminated early, true otherwise. - // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. - bool TraverseTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs); - - /// \brief Recursively visit a constructor initializer. This - /// automatically dispatches to another visitor for the initializer - /// expression, but not for the name of the initializer, so may - /// be overridden for clients that need access to the name. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseConstructorInitializer(CXXCtorInitializer *Init); - - /// \brief Recursively visit a lambda capture. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C); - - /// \brief Recursively visit the body of a lambda expression. - /// - /// This provides a hook for visitors that need more context when visiting - /// \c LE->getBody(). - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr); - - /// \brief Recursively visit the syntactic or semantic form of an - /// initialization list. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseSynOrSemInitListExpr(InitListExpr *S, - DataRecursionQueue *Queue = nullptr); - - // ---- Methods on Attrs ---- - - // \brief Visit an attribute. - bool VisitAttr(Attr *A) { return true; } - -// Declare Traverse* and empty Visit* for all Attr classes. -#define ATTR_VISITOR_DECLS_ONLY -#include "clang/AST/AttrVisitor.inc" -#undef ATTR_VISITOR_DECLS_ONLY - -// ---- Methods on Stmts ---- - -private: - template<typename T, typename U> - struct has_same_member_pointer_type : std::false_type {}; - template<typename T, typename U, typename R, typename... P> - struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> - : std::true_type {}; - - // Traverse the given statement. If the most-derived traverse function takes a - // data recursion queue, pass it on; otherwise, discard it. Note that the - // first branch of this conditional must compile whether or not the derived - // class can take a queue, so if we're taking the second arm, make the first - // arm call our function rather than the derived class version. -#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ - (has_same_member_pointer_type<decltype( \ - &RecursiveASTVisitor::Traverse##NAME), \ - decltype(&Derived::Traverse##NAME)>::value \ - ? static_cast<typename std::conditional< \ - has_same_member_pointer_type< \ - decltype(&RecursiveASTVisitor::Traverse##NAME), \ - decltype(&Derived::Traverse##NAME)>::value, \ - Derived &, RecursiveASTVisitor &>::type>(*this) \ - .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ - : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) - -// Try to traverse the given statement, or enqueue it if we're performing data -// recursion in the middle of traversing another statement. Can only be called -// from within a DEF_TRAVERSE_STMT body or similar context. -#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \ - do { \ - if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \ - return false; \ - } while (0) - -public: -// Declare Traverse*() for all concrete Stmt classes. -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); -#include "clang/AST/StmtNodes.inc" - // The above header #undefs ABSTRACT_STMT and STMT upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. - bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } - bool VisitStmt(Stmt *S) { return true; } -#define STMT(CLASS, PARENT) \ - bool WalkUpFrom##CLASS(CLASS *S) { \ - TRY_TO(WalkUpFrom##PARENT(S)); \ - TRY_TO(Visit##CLASS(S)); \ - return true; \ - } \ - bool Visit##CLASS(CLASS *S) { return true; } -#include "clang/AST/StmtNodes.inc" - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary -// operator methods. Unary operators are not classes in themselves -// (they're all opcodes in UnaryOperator) but do have visitors. -#define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S, \ - DataRecursionQueue *Queue = nullptr) { \ - TRY_TO(WalkUpFromUnary##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ - return true; \ - } \ - bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnaryOperator(S)); \ - TRY_TO(VisitUnary##NAME(S)); \ - return true; \ - } \ - bool VisitUnary##NAME(UnaryOperator *S) { return true; } - - UNARYOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary -// operator methods. Binary operators are not classes in themselves -// (they're all opcodes in BinaryOperator) but do have visitors. -#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ - return true; \ - } \ - bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ - TRY_TO(VisitBin##NAME(S)); \ - return true; \ - } \ - bool VisitBin##NAME(BINOP_TYPE *S) { return true; } - -#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) - BINOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound -// assignment methods. Compound assignment operators are not -// classes in themselves (they're all opcodes in -// CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ - GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) - - CAO_LIST() -#undef OPERATOR -#undef GENERAL_BINOP_FALLBACK - -// ---- Methods on Types ---- -// FIXME: revamp to take TypeLoc's rather than Types. - -// Declare Traverse*() for all concrete Type classes. -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); -#include "clang/AST/TypeNodes.def" - // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Type classes. - bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } - bool VisitType(Type *T) { return true; } -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ - TRY_TO(WalkUpFrom##BASE(T)); \ - TRY_TO(Visit##CLASS##Type(T)); \ - return true; \ - } \ - bool Visit##CLASS##Type(CLASS##Type *T) { return true; } -#include "clang/AST/TypeNodes.def" - -// ---- Methods on TypeLocs ---- -// FIXME: this currently just calls the matching Type methods - -// Declare Traverse*() for all concrete TypeLoc classes. -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); -#include "clang/AST/TypeLocNodes.def" - // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. - bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } - bool VisitTypeLoc(TypeLoc TL) { return true; } - - // QualifiedTypeLoc and UnqualTypeLoc are not declared in - // TypeNodes.def and thus need to be handled specially. - bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } - bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } - -// Note that BASE includes trailing 'Type' which CLASS doesn't. -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ - TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ - TRY_TO(Visit##CLASS##TypeLoc(TL)); \ - return true; \ - } \ - bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } -#include "clang/AST/TypeNodes.def" - -// ---- Methods on Decls ---- - -// Declare Traverse*() for all concrete Decl classes. -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); -#include "clang/AST/DeclNodes.inc" - // The above header #undefs ABSTRACT_DECL and DECL upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Decl classes. - bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } - bool VisitDecl(Decl *D) { return true; } -#define DECL(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ - TRY_TO(WalkUpFrom##BASE(D)); \ - TRY_TO(Visit##CLASS##Decl(D)); \ - return true; \ - } \ - bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } -#include "clang/AST/DeclNodes.inc" - -private: - // These are helper methods used by more than one Traverse* method. - bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); -#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ - bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); - DEF_TRAVERSE_TMPL_INST(Class) - DEF_TRAVERSE_TMPL_INST(Var) - DEF_TRAVERSE_TMPL_INST(Function) -#undef DEF_TRAVERSE_TMPL_INST - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, - unsigned Count); - bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); - bool TraverseRecordHelper(RecordDecl *D); - bool TraverseCXXRecordHelper(CXXRecordDecl *D); - bool TraverseDeclaratorHelper(DeclaratorDecl *D); - bool TraverseDeclContextHelper(DeclContext *DC); - bool TraverseFunctionHelper(FunctionDecl *D); - bool TraverseVarHelper(VarDecl *D); - bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); - bool TraverseOMPLoopDirective(OMPLoopDirective *S); - bool TraverseOMPClause(OMPClause *C); -#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); -#include "clang/Basic/OpenMPKinds.def" - /// \brief Process clauses with list of variables. - template <typename T> bool VisitOMPClauseList(T *Node); - - bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); -}; - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, - DataRecursionQueue *Queue) { -#define DISPATCH_STMT(NAME, CLASS, VAR) \ - return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue); - - // If we have a binary expr, dispatch to the subcode of the binop. A smart - // optimizer (e.g. LLVM) will fold this comparison into the switch stmt - // below. - if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { - switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: \ - DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - - BINOP_LIST() -#undef OPERATOR -#undef BINOP_LIST - -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); - - CAO_LIST() -#undef OPERATOR -#undef CAO_LIST - } - } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { - switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: \ - DISPATCH_STMT(Unary##NAME, UnaryOperator, S); - - UNARYOP_LIST() -#undef OPERATOR -#undef UNARYOP_LIST - } - } - - // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. - switch (S->getStmtClass()) { - case Stmt::NoStmtClass: - break; -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: \ - DISPATCH_STMT(CLASS, CLASS, S); -#include "clang/AST/StmtNodes.inc" - } - - return true; -} - -#undef DISPATCH_STMT - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, - DataRecursionQueue *Queue) { - if (!S) - return true; - - if (Queue) { - Queue->push_back(S); - return true; - } - - SmallVector<Stmt *, 8> LocalQueue; - LocalQueue.push_back(S); - - while (!LocalQueue.empty()) { - Stmt *CurrS = LocalQueue.pop_back_val(); - - size_t N = LocalQueue.size(); - TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); - // Process new children in the order they were added. - std::reverse(LocalQueue.begin() + N, LocalQueue.end()); - } - - return true; -} - -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { - if (T.isNull()) - return true; - - switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - case Type::CLASS: \ - DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); -#include "clang/AST/TypeNodes.def" - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { - if (TL.isNull()) - return true; - - switch (TL.getTypeLocClass()) { -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - case TypeLoc::CLASS: \ - return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); -#include "clang/AST/TypeLocNodes.def" - } - - return true; -} - -// Define the Traverse*Attr(Attr* A) methods -#define VISITORCLASS RecursiveASTVisitor -#include "clang/AST/AttrVisitor.inc" -#undef VISITORCLASS - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { - if (!D) - return true; - - // As a syntax visitor, by default we want to ignore declarations for - // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) - return true; - - switch (D->getKind()) { -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - case Decl::CLASS: \ - if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ - return false; \ - break; -#include "clang/AST/DeclNodes.inc" - } - - // Visit any attributes attached to this declaration. - for (auto *I : D->attrs()) { - if (!getDerived().TraverseAttr(I)) - return false; - } - return true; -} - -#undef DISPATCH - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( - NestedNameSpecifier *NNS) { - if (!NNS) - return true; - - if (NNS->getPrefix()) - TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( - NestedNameSpecifierLoc NNS) { - if (!NNS) - return true; - - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); - - switch (NNS.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); - break; - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( - DeclarationNameInfo NameInfo) { - switch (NameInfo.getName().getNameKind()) { - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) - TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); - - break; - - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXOperatorName: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXUsingDirective: - break; - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { - if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); - else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( - const TemplateArgument &Arg) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: - return getDerived().TraverseType(Arg.getAsType()); - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(Arg.getAsExpr()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -// FIXME: no template name location? -// FIXME: no source locations for a template argument pack? -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( - const TemplateArgumentLoc &ArgLoc) { - const TemplateArgument &Arg = ArgLoc.getArgument(); - - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: { - // FIXME: how can TSI ever be NULL? - if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) - return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return getDerived().TraverseType(Arg.getAsType()); - } - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - if (ArgLoc.getTemplateQualifierLoc()) - TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( - ArgLoc.getTemplateQualifierLoc())); - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( - const TemplateArgument *Args, unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) { - TRY_TO(TraverseTemplateArgument(Args[I])); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( - CXXCtorInitializer *Init) { - if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - - if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) - TRY_TO(TraverseStmt(Init->getInit())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, - const LambdaCapture *C) { - if (LE->isInitCapture(C)) - TRY_TO(TraverseDecl(C->getCapturedVar())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaBody( - LambdaExpr *LE, DataRecursionQueue *Queue) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody()); - return true; -} - -// ----------------- Type traversal ----------------- - -// This macro makes available a variable T, the passed-in type. -#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ - TRY_TO(WalkUpFrom##TYPE(T)); \ - { CODE; } \ - return true; \ - } - -DEF_TRAVERSE_TYPE(BuiltinType, {}) - -DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(BlockPointerType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(LValueReferenceType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(RValueReferenceType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(MemberPointerType, { - TRY_TO(TraverseType(QualType(T->getClass(), 0))); - TRY_TO(TraverseType(T->getPointeeType())); -}) - -DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) - -DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) - -DEF_TRAVERSE_TYPE(ConstantArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(IncompleteArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(VariableArrayType, { - TRY_TO(TraverseType(T->getElementType())); - TRY_TO(TraverseStmt(T->getSizeExpr())); -}) - -DEF_TRAVERSE_TYPE(DependentSizedArrayType, { - TRY_TO(TraverseType(T->getElementType())); - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); -}) - -DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - TRY_TO(TraverseType(T->getElementType())); -}) - -DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(FunctionNoProtoType, - { TRY_TO(TraverseType(T->getReturnType())); }) - -DEF_TRAVERSE_TYPE(FunctionProtoType, { - TRY_TO(TraverseType(T->getReturnType())); - - for (const auto &A : T->param_types()) { - TRY_TO(TraverseType(A)); - } - - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); -}) - -DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) -DEF_TRAVERSE_TYPE(TypedefType, {}) - -DEF_TRAVERSE_TYPE(TypeOfExprType, - { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) - -DEF_TRAVERSE_TYPE(DecltypeType, - { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPE(UnaryTransformType, { - TRY_TO(TraverseType(T->getBaseType())); - TRY_TO(TraverseType(T->getUnderlyingType())); -}) - -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())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); -}) - -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())); - } - TRY_TO(TraverseType(T->getNamedType())); -}) - -DEF_TRAVERSE_TYPE(DependentNameType, - { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) - -DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); -}) - -DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) - -DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) - -DEF_TRAVERSE_TYPE(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (T->getBaseType().getTypePtr() != T) - TRY_TO(TraverseType(T->getBaseType())); - for (auto typeArg : T->getTypeArgsAsWritten()) { - TRY_TO(TraverseType(typeArg)); - } -}) - -DEF_TRAVERSE_TYPE(ObjCObjectPointerType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) - -#undef DEF_TRAVERSE_TYPE - -// ----------------- TypeLoc traversal ----------------- - -// This macro makes available a variable TL, the passed-in TypeLoc. -// 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) { \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ - TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ - TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - { CODE; } \ - return true; \ - } - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { - // Move this over to the 'main' typeloc tree. Note that this is a - // move -- we pretend that we were really looking at the unqualified - // typeloc all along -- rather than a recursion, so we don't follow - // the normal CRTP plan of going through - // getDerived().TraverseTypeLoc. If we did, we'd be traversing - // twice for the same type (once as a QualifiedTypeLoc version of - // the type, once as an UnqualifiedTypeLoc version of the type), - // which in effect means we'd call VisitTypeLoc twice with the - // 'same' type. This solves that problem, at the cost of never - // seeing the qualified version of the type (unless the client - // subclasses TraverseQualifiedTypeLoc themselves). It's not a - // perfect solution. A perfect solution probably requires making - // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a - // wrapper around Type* -- rather than being its own class in the - // type hierarchy. - return TraverseTypeLoc(TL.getUnqualifiedLoc()); -} - -DEF_TRAVERSE_TYPELOC(BuiltinType, {}) - -// FIXME: ComplexTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ComplexType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -DEF_TRAVERSE_TYPELOC(PointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(BlockPointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(LValueReferenceType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(RValueReferenceType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -// FIXME: location of base class? -// We traverse this in the type case as well, but how is it not reached through -// the pointee type? -DEF_TRAVERSE_TYPELOC(MemberPointerType, { - TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(AdjustedType, - { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) - -DEF_TRAVERSE_TYPELOC(DecayedType, - { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { - // This isn't available for ArrayType, but is for the ArrayTypeLoc. - TRY_TO(TraverseStmt(TL.getSizeExpr())); - return true; -} - -DEF_TRAVERSE_TYPELOC(ConstantArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(VariableArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -// FIXME: order? why not size expr first? -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -// FIXME: VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(VectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -// FIXME: size and attributes -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ExtVectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, - { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) - -// FIXME: location of exception specifications (attributes?) -DEF_TRAVERSE_TYPELOC(FunctionProtoType, { - TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); - - const FunctionProtoType *T = TL.getTypePtr(); - - for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { - if (TL.getParam(I)) { - TRY_TO(TraverseDecl(TL.getParam(I))); - } else if (I < T->getNumParams()) { - TRY_TO(TraverseType(T->getParamType(I))); - } - } - - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); -}) - -DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) -DEF_TRAVERSE_TYPELOC(TypedefType, {}) - -DEF_TRAVERSE_TYPELOC(TypeOfExprType, - { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPELOC(TypeOfType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); -}) - -// FIXME: location of underlying expr -DEF_TRAVERSE_TYPELOC(DecltypeType, { - TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); -}) - -DEF_TRAVERSE_TYPELOC(UnaryTransformType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); -}) - -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, { - TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } -}) - -DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) - -DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) - -DEF_TRAVERSE_TYPELOC(AttributedType, - { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) - -DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); -}) - -DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } -}) - -DEF_TRAVERSE_TYPELOC(PackExpansionType, - { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) - -DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) - -DEF_TRAVERSE_TYPELOC(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) - TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); - for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) - TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) - -#undef DEF_TRAVERSE_TYPELOC - -// ----------------- Decl traversal ----------------- -// -// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing -// the children that come from the DeclContext associated with it. -// Therefore each Traverse* only needs to worry about children other -// than those. - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { - if (!DC) - return true; - - for (auto *Child : DC->decls()) { - // BlockDecls and CapturedDecls are traversed through BlockExprs and - // CapturedStmts respectively. - if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child)) - TRY_TO(TraverseDecl(Child)); - } - - return true; -} - -// This macro makes available a variable D, the passed-in decl. -#define DEF_TRAVERSE_DECL(DECL, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ - TRY_TO(WalkUpFrom##DECL(D)); \ - { CODE; } \ - TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ - return true; \ - } - -DEF_TRAVERSE_DECL(AccessSpecDecl, {}) - -DEF_TRAVERSE_DECL(BlockDecl, { - if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - TRY_TO(TraverseStmt(D->getBody())); - for (const auto &I : D->captures()) { - if (I.hasCopyExpr()) { - TRY_TO(TraverseStmt(I.getCopyExpr())); - } - } - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; -}) - -DEF_TRAVERSE_DECL(CapturedDecl, { - TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; -}) - -DEF_TRAVERSE_DECL(EmptyDecl, {}) - -DEF_TRAVERSE_DECL(FileScopeAsmDecl, - { TRY_TO(TraverseStmt(D->getAsmString())); }) - -DEF_TRAVERSE_DECL(ImportDecl, {}) - -DEF_TRAVERSE_DECL(FriendDecl, { - // 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, { - 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(), ETPL = TPL->end(); - ITPL != ETPL; ++ITPL) { - TRY_TO(TraverseDecl(*ITPL)); - } - } -}) - -DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { - TRY_TO(TraverseDecl(D->getSpecialization())); - - if (D->hasExplicitTemplateArgs()) { - const TemplateArgumentListInfo &args = D->templateArgs(); - TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(), - args.size())); - } -}) - -DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) - -DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this - }) - -DEF_TRAVERSE_DECL(StaticAssertDecl, { - TRY_TO(TraverseStmt(D->getAssertExpr())); - TRY_TO(TraverseStmt(D->getMessage())); -}) - -DEF_TRAVERSE_DECL( - TranslationUnitDecl, - {// Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(ExternCContextDecl, {}) - -DEF_TRAVERSE_DECL(NamespaceAliasDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - - // We shouldn't traverse an aliased namespace, since it will be - // defined (and, therefore, traversed) somewhere else. - // - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - 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 - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement - if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { - for (auto typeParam : *typeParamList) { - TRY_TO(TraverseObjCTypeParamDecl(typeParam)); - } - } -}) - -DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement - if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { - for (auto typeParam : *typeParamList) { - TRY_TO(TraverseObjCTypeParamDecl(typeParam)); - } - } - - if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { - TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); - } -}) - -DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCMethodDecl, { - if (D->getReturnTypeSourceInfo()) { - TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); - } - for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); - } - return true; -}) - -DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { - if (D->hasExplicitBound()) { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type alias, not something that was written in the - // source. - } -}) - -DEF_TRAVERSE_DECL(ObjCPropertyDecl, { - if (D->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - else - TRY_TO(TraverseType(D->getType())); - return true; -}) - -DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); -}) - -DEF_TRAVERSE_DECL(UsingDirectiveDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); -}) - -DEF_TRAVERSE_DECL(UsingShadowDecl, {}) - -DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { - for (auto *I : D->varlists()) { - TRY_TO(TraverseStmt(I)); - } -}) - -// A helper method for TemplateDecl's children. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( - TemplateParameterList *TPL) { - if (TPL) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( - ClassTemplateDecl *D) { - for (auto *SD : D->specializations()) { - for (auto *RD : SD->redecls()) { - // We don't want to visit injected-class-names in this traversal. - if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) - continue; - - switch ( - cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(RD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( - VarTemplateDecl *D) { - for (auto *SD : D->specializations()) { - for (auto *RD : SD->redecls()) { - switch ( - cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(RD)); - break; - - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -// A helper method for traversing the instantiations of a -// function while skipping its specializations. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( - FunctionTemplateDecl *D) { - for (auto *FD : D->specializations()) { - for (auto *RD : FD->redecls()) { - switch (RD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - // We don't know what kind of FunctionDecl this is. - TRY_TO(TraverseDecl(RD)); - break; - - // FIXME: For now traverse explicit instantiations here. Change that - // once they are represented as dedicated nodes in the AST. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - TRY_TO(TraverseDecl(RD)); - break; - - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -// This macro unifies the traversal of class, variable and function -// template declarations. -#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ - DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ - TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ - \ - /* By default, we do not traverse the instantiations of \ - class templates since they do not appear in the user code. The \ - following code optionally traverses them. \ - \ - We only traverse the class instantiations when we see the canonical \ - declaration of the template, to ensure we only visit them once. */ \ - if (getDerived().shouldVisitTemplateInstantiations() && \ - D == D->getCanonicalDecl()) \ - TRY_TO(TraverseTemplateInstantiations(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. */ \ - }) - -DEF_TRAVERSE_TMPL_DECL(Class) -DEF_TRAVERSE_TMPL_DECL(Var) -DEF_TRAVERSE_TMPL_DECL(Function) - -DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { - // D is the "T" in something like - // template <template <typename> class T> class container { }; - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); - } - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); -}) - -DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); -}) - -DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { - // D is the "T" in something like "template<typename T> class vector;" - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_DECL(TypedefDecl, { - 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. -}) - -DEF_TRAVERSE_DECL(TypeAliasDecl, { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type alias, not something that was written in the - // source. -}) - -DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); -}) - -DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { - // A dependent using declaration which was marked with 'typename'. - // template<class T> class A : public B<T> { using typename B<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type, not something that was written in the - // source. -}) - -DEF_TRAVERSE_DECL(EnumDecl, { - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // The enumerators are already traversed by - // decls_begin()/decls_end(). -}) - -// Helper methods for RecordDecl and its children. -template <typename Derived> -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. - - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { - if (!TraverseRecordHelper(D)) - return false; - if (D->isCompleteDefinition()) { - for (const auto &I : D->bases()) { - TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc())); - } - // We don't traverse the friends or the conversions, as they are - // already in decls_begin()/decls_end(). - } - return true; -} - -DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) - -DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) - -#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ - DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ - /* For implicit instantiations ("set<int> x;"), we don't want to \ - recurse at all, since the instatiated template isn't written in \ - the source code anywhere. (Note the instatiated *type* -- \ - set<int> -- is written, and will still get a callback of \ - TemplateSpecializationType). For explicit instantiations \ - ("template set<int>;"), we do need a callback, since this \ - is the only callback that's made for this instantiation. \ - We use getTypeAsWritten() to distinguish. */ \ - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ - \ - if (!getDerived().shouldVisitTemplateInstantiations() && \ - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ - /* Returning from here skips traversing the \ - declaration context of the *TemplateSpecializationDecl \ - (embedded in the DEF_TRAVERSE_DECL() macro) \ - which contains the instantiated members of the template. */ \ - return true; \ - }) - -DEF_TRAVERSE_TMPL_SPEC_DECL(Class) -DEF_TRAVERSE_TMPL_SPEC_DECL(Var) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( - const TemplateArgumentLoc *TAL, unsigned Count) { - for (unsigned I = 0; I < Count; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); - } - return true; -} - -#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ - DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ - /* The partial specialization. */ \ - if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ - I != E; ++I) { \ - TRY_TO(TraverseDecl(*I)); \ - } \ - } \ - /* The args that remains unspecialized. */ \ - TRY_TO(TraverseTemplateArgumentLocsHelper( \ - D->getTemplateArgsAsWritten()->getTemplateArgs(), \ - D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ - \ - /* Don't need the *TemplatePartialSpecializationHelper, even \ - though that's our parent class -- we already visit all the \ - template args here. */ \ - TRY_TO(Traverse##DECLKIND##Helper(D)); \ - \ - /* Instantiations will have been visited with the primary template. */ \ - }) - -DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) -DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) - -DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) - -DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { - // Like UnresolvedUsingTypenameDecl, but without the 'typename': - // template <class T> Class A : public Base<T> { using Base<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); -}) - -DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - if (D->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - else - TRY_TO(TraverseType(D->getType())); - return true; -} - -DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) - -DEF_TRAVERSE_DECL(FieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - else if (D->hasInClassInitializer()) - TRY_TO(TraverseStmt(D->getInClassInitializer())); -}) - -DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. -}) - -DEF_TRAVERSE_DECL(ObjCIvarDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); - - // If we're an explicit template specialization, iterate over the - // 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 && - FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { - // A specialization might not have explicit template arguments if it has - // a templated return type and concrete arguments. - if (const ASTTemplateArgumentListInfo *TALI = - FTSI->TemplateArgumentsAsWritten) { - TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), - TALI->NumTemplateArgs)); - } - } - } - - // 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. - if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - } else if (getDerived().shouldVisitImplicitCode()) { - // Visit parameter variable declarations of the implicit function - // if the traverser is visiting implicit code. Parameter variable - // declarations do not have valid TypeSourceInfo, so to visit them - // we need to traverse the declarations explicitly. - for (FunctionDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); - I != E; ++I) - TRY_TO(TraverseDecl(*I)); - } - - if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { - // Constructor initializers. - for (auto *I : Ctor->inits()) { - TRY_TO(TraverseConstructorInitializer(I)); - } - } - - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); // Function body. - } - return true; -} - -DEF_TRAVERSE_DECL(FunctionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXMethodDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXConstructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -// CXXConversionDecl is the declaration of a type conversion operator. -// It's not a cast expression. -DEF_TRAVERSE_DECL(CXXConversionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXDestructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { - TRY_TO(TraverseDeclaratorHelper(D)); - // Default params are taken care of when we traverse the ParmVarDecl. - if (!isa<ParmVarDecl>(D) && - (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode())) - TRY_TO(TraverseStmt(D->getInit())); - return true; -} - -DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) - -DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) - -DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { - // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseStmt(D->getDefaultArgument())); -}) - -DEF_TRAVERSE_DECL(ParmVarDecl, { - TRY_TO(TraverseVarHelper(D)); - - if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); - - if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getDefaultArg())); -}) - -#undef DEF_TRAVERSE_DECL - -// ----------------- Stmt traversal ----------------- -// -// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating -// 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) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##STMT( \ - STMT *S, DataRecursionQueue *Queue) { \ - TRY_TO(WalkUpFrom##STMT(S)); \ - { CODE; } \ - for (Stmt *SubStmt : S->children()) { \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ - } \ - return true; \ - } - -DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); - for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); - } - for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); - } - for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); - } - // children() iterates over inputExpr and outputExpr. -}) - -DEF_TRAVERSE_STMT( - MSAsmStmt, - {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once - // added this needs to be implemented. - }) - -DEF_TRAVERSE_STMT(CXXCatchStmt, { - TRY_TO(TraverseDecl(S->getExceptionDecl())); - // children() iterates over the handler block. -}) - -DEF_TRAVERSE_STMT(DeclStmt, { - for (auto *I : S->decls()) { - TRY_TO(TraverseDecl(I)); - } - // 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 - // children() would do). - return true; -}) - -// These non-expr stmts (most of them), do not need any action except -// iterating over the children. -DEF_TRAVERSE_STMT(BreakStmt, {}) -DEF_TRAVERSE_STMT(CXXTryStmt, {}) -DEF_TRAVERSE_STMT(CaseStmt, {}) -DEF_TRAVERSE_STMT(CompoundStmt, {}) -DEF_TRAVERSE_STMT(ContinueStmt, {}) -DEF_TRAVERSE_STMT(DefaultStmt, {}) -DEF_TRAVERSE_STMT(DoStmt, {}) -DEF_TRAVERSE_STMT(ForStmt, {}) -DEF_TRAVERSE_STMT(GotoStmt, {}) -DEF_TRAVERSE_STMT(IfStmt, {}) -DEF_TRAVERSE_STMT(IndirectGotoStmt, {}) -DEF_TRAVERSE_STMT(LabelStmt, {}) -DEF_TRAVERSE_STMT(AttributedStmt, {}) -DEF_TRAVERSE_STMT(NullStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtTryStmt, {}) -DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) -DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) -DEF_TRAVERSE_STMT(CXXForRangeStmt, { - if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt()); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit()); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); - // Visit everything else only if shouldVisitImplicitCode(). - return true; - } -}) -DEF_TRAVERSE_STMT(MSDependentExistsStmt, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); -}) -DEF_TRAVERSE_STMT(ReturnStmt, {}) -DEF_TRAVERSE_STMT(SwitchStmt, {}) -DEF_TRAVERSE_STMT(WhileStmt, {}) - -DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); -}) - -DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(MemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); -}) - -DEF_TRAVERSE_STMT( - ImplicitCastExpr, - {// We don't traverse the cast type, as it's not written in the - // source code. - }) - -DEF_TRAVERSE_STMT(CStyleCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXConstCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXStaticCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( - InitListExpr *S, DataRecursionQueue *Queue) { - if (S) { - TRY_TO(WalkUpFromInitListExpr(S)); - // All we need are the default actions. FIXME: use a helper function. - for (Stmt *SubStmt : S->children()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); - } - } - return true; -} - -// This method is called once for each pair of syntactic and semantic -// InitListExpr, and it traverses the subtrees defined by the two forms. This -// may cause some of the children to be visited twice, if they appear both in -// the syntactic and the semantic form. -// -// There is no guarantee about which form \p S takes when this method is called. -DEF_TRAVERSE_STMT(InitListExpr, { - TRY_TO(TraverseSynOrSemInitListExpr( - S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); - TRY_TO(TraverseSynOrSemInitListExpr( - S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); - return true; -}) - -// GenericSelectionExpr is a special case because the types and expressions -// are interleaved. We also need to watch out for null types (default -// generic associations). -DEF_TRAVERSE_STMT(GenericSelectionExpr, { - TRY_TO(TraverseStmt(S->getControllingExpr())); - for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) - TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i)); - } - return true; -}) - -// PseudoObjectExpr is a special case because of the weirdness with -// syntactic expressions and opaque values. -DEF_TRAVERSE_STMT(PseudoObjectExpr, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm()); - for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), - e = S->semantics_end(); - i != e; ++i) { - Expr *sub = *i; - if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) - sub = OVE->getSourceExpr(); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub); - } - return true; -}) - -DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { - // This is called for code like 'return T()' where T is a built-in - // (i.e. non-class) type. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXNewExpr, { - // The child-iterator will pick up the other arguments. - TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(OffsetOfExpr, { - // The child-iterator will pick up the expression representing - // the field. - // FIMXE: for code like offsetof(Foo, a.b.c), should we get - // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isArgumentType()) - TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXTypeidExpr, { - // 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(MSPropertyRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); -}) - -DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {}) - -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(TypeTraitExpr, { - for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) - TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { - TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(ExpressionTraitExpr, - { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); }) - -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())); -}) - -// Walk only the visible parts of lambda expressions. -DEF_TRAVERSE_STMT(LambdaExpr, { - for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), - CEnd = S->explicit_capture_end(); - C != CEnd; ++C) { - TRY_TO(TraverseLambdaCapture(S, C)); - } - - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); - - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else if (S->hasExplicitResultType()) { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); - } - - auto *T = Proto.getTypePtr(); - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); - } - - return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue); -}) - -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, {}) -DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) -DEF_TRAVERSE_STMT(OMPArraySectionExpr, {}) -DEF_TRAVERSE_STMT(BlockExpr, { - TRY_TO(TraverseDecl(S->getBlockDecl())); - return true; // no child statements to loop through. -}) -DEF_TRAVERSE_STMT(ChooseExpr, {}) -DEF_TRAVERSE_STMT(CompoundLiteralExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {}) -DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {}) -DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {}) -DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) -DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) -DEF_TRAVERSE_STMT(ExprWithCleanups, {}) -DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) -DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) -DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - 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(UserDefinedLiteral, {}) -DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) -DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) -DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) -DEF_TRAVERSE_STMT(GNUNullExpr, {}) -DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) -DEF_TRAVERSE_STMT(NoInitExpr, {}) -DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) -DEF_TRAVERSE_STMT(ObjCEncodeExpr, { - if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ObjCIsaExpr, {}) -DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCMessageExpr, { - if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) -DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) -DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) -DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ParenExpr, {}) -DEF_TRAVERSE_STMT(ParenListExpr, {}) -DEF_TRAVERSE_STMT(PredefinedExpr, {}) -DEF_TRAVERSE_STMT(ShuffleVectorExpr, {}) -DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) -DEF_TRAVERSE_STMT(StmtExpr, {}) -DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(SEHTryStmt, {}) -DEF_TRAVERSE_STMT(SEHExceptStmt, {}) -DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) -DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) -DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) - -DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) -DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) -DEF_TRAVERSE_STMT(TypoExpr, {}) -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, {}) -DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) -DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) -DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) -DEF_TRAVERSE_STMT(CXXFoldExpr, {}) -DEF_TRAVERSE_STMT(AtomicExpr, {}) - -// For coroutines expressions, traverse either the operand -// as written or the implied calls, depending on what the -// derived class requests. -DEF_TRAVERSE_STMT(CoroutineBodyStmt, { - if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); - return true; - } -}) -DEF_TRAVERSE_STMT(CoreturnStmt, { - if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; - } -}) -DEF_TRAVERSE_STMT(CoawaitExpr, { - if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; - } -}) -DEF_TRAVERSE_STMT(CoyieldExpr, { - if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; - } -}) - -// These literals (all of them) do not need any action. -DEF_TRAVERSE_STMT(IntegerLiteral, {}) -DEF_TRAVERSE_STMT(CharacterLiteral, {}) -DEF_TRAVERSE_STMT(FloatingLiteral, {}) -DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) -DEF_TRAVERSE_STMT(StringLiteral, {}) -DEF_TRAVERSE_STMT(ObjCStringLiteral, {}) -DEF_TRAVERSE_STMT(ObjCBoxedExpr, {}) -DEF_TRAVERSE_STMT(ObjCArrayLiteral, {}) -DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {}) - -// Traverse OpenCL: AsType, Convert. -DEF_TRAVERSE_STMT(AsTypeExpr, {}) - -// OpenMP directives. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( - OMPExecutableDirective *S) { - for (auto *C : S->clauses()) { - TRY_TO(TraverseOMPClause(C)); - } - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { - return TraverseOMPExecutableDirective(S); -} - -DEF_TRAVERSE_STMT(OMPParallelDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPForDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPForSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSectionsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSectionDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSingleDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPMasterDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCriticalDirective, { - TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); - TRY_TO(TraverseOMPExecutableDirective(S)); -}) - -DEF_TRAVERSE_STMT(OMPParallelForDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskyieldDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPBarrierDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskwaitDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskgroupDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCancellationPointDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCancelDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPFlushDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPOrderedDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPAtomicDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTargetDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTargetDataDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTeamsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskLoopDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPDistributeDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -// OpenMP clauses. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { - if (!C) - return true; - switch (C->getClauseKind()) { -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_##Name: \ - TRY_TO(Visit##Class(static_cast<Class *>(C))); \ - break; -#include "clang/Basic/OpenMPKinds.def" - case OMPC_threadprivate: - case OMPC_unknown: - break; - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { - TRY_TO(TraverseStmt(C->getCondition())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { - TRY_TO(TraverseStmt(C->getCondition())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { - TRY_TO(TraverseStmt(C->getNumThreads())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { - TRY_TO(TraverseStmt(C->getSafelen())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) { - TRY_TO(TraverseStmt(C->getSimdlen())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { - TRY_TO(TraverseStmt(C->getNumForLoops())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) { - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { - TRY_TO(TraverseStmt(C->getChunkSize())); - TRY_TO(TraverseStmt(C->getHelperChunkSize())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) { - TRY_TO(TraverseStmt(C->getNumForLoops())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) { - return true; -} - -template <typename Derived> -template <typename T> -bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { - for (auto *E : Node->varlists()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( - OMPFirstprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->inits()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause( - OMPLastprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { - TRY_TO(TraverseStmt(C->getStep())); - TRY_TO(TraverseStmt(C->getCalcStep())); - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->privates()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->inits()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->updates()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->finals()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) { - TRY_TO(TraverseStmt(C->getAlignment())); - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause( - OMPCopyprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { - TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->privates()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->lhs_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->rhs_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->reduction_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) { - TRY_TO(TraverseStmt(C->getDevice())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause( - OMPNumTeamsClause *C) { - TRY_TO(TraverseStmt(C->getNumTeams())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause( - OMPThreadLimitClause *C) { - TRY_TO(TraverseStmt(C->getThreadLimit())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause( - OMPPriorityClause *C) { - TRY_TO(TraverseStmt(C->getPriority())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause( - OMPGrainsizeClause *C) { - TRY_TO(TraverseStmt(C->getGrainsize())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause( - OMPNumTasksClause *C) { - TRY_TO(TraverseStmt(C->getNumTasks())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) { - TRY_TO(TraverseStmt(C->getHint())); - return true; -} - -// FIXME: look at the following tricky-seeming exprs to see if we -// need to recurse on anything. These are ones that have methods -// returning decls or qualtypes or nestednamespecifier -- though I'm -// not sure if they own them -- or just seemed very complicated, or -// had lots of sub-types to explore. -// -// VisitOverloadExpr and its children: recurse on template args? etc? - -// FIXME: go through all the stmts and exprs again, and see which of them -// create new types, and recurse on the types (TypeLocs?) of those. -// Candidates: -// -// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html -// Every class that has getQualifier. - -#undef DEF_TRAVERSE_STMT -#undef TRAVERSE_STMT -#undef TRAVERSE_STMT_BASE - -#undef TRY_TO - -} // end namespace clang - -#endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h deleted file mode 100644 index eaa22f8..0000000 --- a/include/clang/AST/Redeclarable.h +++ /dev/null @@ -1,285 +0,0 @@ -//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the Redeclarable interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_REDECLARABLE_H -#define LLVM_CLANG_AST_REDECLARABLE_H - -#include "clang/AST/ExternalASTSource.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Casting.h" -#include <iterator> - -namespace clang { -class ASTContext; - -/// \brief Provides common interface for the Decls that can be redeclared. -template<typename decl_type> -class Redeclarable { -protected: - class DeclLink { - /// A pointer to a known latest declaration, either statically known or - /// generationally updated as decls are added by an external source. - typedef LazyGenerationalUpdatePtr<const Decl*, Decl*, - &ExternalASTSource::CompleteRedeclChain> - KnownLatest; - - /// We store a pointer to the ASTContext in the UninitializedLatest - /// pointer, but to avoid circular type dependencies when we steal the low - /// bits of this pointer, we use a raw void* here. - typedef const void *UninitializedLatest; - - typedef Decl *Previous; - - /// A pointer to either an uninitialized latest declaration (where either - /// we've not yet set the previous decl or there isn't one), or to a known - /// previous declaration. - typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest; - - mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next; - - public: - enum PreviousTag { PreviousLink }; - enum LatestTag { LatestLink }; - - DeclLink(LatestTag, const ASTContext &Ctx) - : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {} - DeclLink(PreviousTag, decl_type *D) - : Next(NotKnownLatest(Previous(D))) {} - - bool NextIsPrevious() const { - return Next.is<NotKnownLatest>() && - // FIXME: 'template' is required on the next line due to an - // apparent clang bug. - Next.get<NotKnownLatest>().template is<Previous>(); - } - - bool NextIsLatest() const { return !NextIsPrevious(); } - - decl_type *getNext(const decl_type *D) const { - if (Next.is<NotKnownLatest>()) { - NotKnownLatest NKL = Next.get<NotKnownLatest>(); - if (NKL.is<Previous>()) - return static_cast<decl_type*>(NKL.get<Previous>()); - - // Allocate the generational 'most recent' cache now, if needed. - Next = KnownLatest(*reinterpret_cast<const ASTContext *>( - NKL.get<UninitializedLatest>()), - const_cast<decl_type *>(D)); - } - - return static_cast<decl_type*>(Next.get<KnownLatest>().get(D)); - } - - void setPrevious(decl_type *D) { - assert(NextIsPrevious() && "decl became non-canonical unexpectedly"); - Next = Previous(D); - } - - void setLatest(decl_type *D) { - assert(NextIsLatest() && "decl became canonical unexpectedly"); - if (Next.is<NotKnownLatest>()) { - NotKnownLatest NKL = Next.get<NotKnownLatest>(); - Next = KnownLatest(*reinterpret_cast<const ASTContext *>( - NKL.get<UninitializedLatest>()), - D); - } else { - auto Latest = Next.get<KnownLatest>(); - Latest.set(D); - Next = Latest; - } - } - - void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); } - - Decl *getLatestNotUpdated() const { - assert(NextIsLatest() && "expected a canonical decl"); - if (Next.is<NotKnownLatest>()) - return nullptr; - return Next.get<KnownLatest>().getNotUpdated(); - } - }; - - static DeclLink PreviousDeclLink(decl_type *D) { - return DeclLink(DeclLink::PreviousLink, D); - } - - static DeclLink LatestDeclLink(const ASTContext &Ctx) { - return DeclLink(DeclLink::LatestLink, Ctx); - } - - /// \brief Points to the next redeclaration in the chain. - /// - /// If NextIsPrevious() is true, this is a link to the previous declaration - /// of this same Decl. If NextIsLatest() is true, this is the first - /// declaration and Link points to the latest declaration. For example: - /// - /// #1 int f(int x, int y = 1); // <pointer to #3, true> - /// #2 int f(int x = 0, int y); // <pointer to #1, false> - /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false> - /// - /// If there is only one declaration, it is <pointer to self, true> - DeclLink RedeclLink; - decl_type *First; - - decl_type *getNextRedeclaration() const { - return RedeclLink.getNext(static_cast<const decl_type *>(this)); - } - -public: - Redeclarable(const ASTContext &Ctx) - : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {} - - /// \brief Return the previous declaration of this declaration or NULL if this - /// is the first declaration. - decl_type *getPreviousDecl() { - if (RedeclLink.NextIsPrevious()) - return getNextRedeclaration(); - return nullptr; - } - const decl_type *getPreviousDecl() const { - return const_cast<decl_type *>( - static_cast<const decl_type*>(this))->getPreviousDecl(); - } - - /// \brief Return the first declaration of this declaration or itself if this - /// is the only declaration. - decl_type *getFirstDecl() { return First; } - - /// \brief Return the first declaration of this declaration or itself if this - /// is the only declaration. - const decl_type *getFirstDecl() const { return First; } - - /// \brief True if this is the first declaration in its redeclaration chain. - bool isFirstDecl() const { return RedeclLink.NextIsLatest(); } - - /// \brief Returns the most recent (re)declaration of this declaration. - decl_type *getMostRecentDecl() { - return getFirstDecl()->getNextRedeclaration(); - } - - /// \brief Returns the most recent (re)declaration of this declaration. - const decl_type *getMostRecentDecl() const { - return getFirstDecl()->getNextRedeclaration(); - } - - /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the - /// first and only declaration. - void setPreviousDecl(decl_type *PrevDecl); - - /// \brief Iterates through all the redeclarations of the same decl. - class redecl_iterator { - /// Current - The current declaration. - decl_type *Current; - decl_type *Starter; - bool PassedFirst; - - public: - typedef decl_type* value_type; - typedef decl_type* reference; - typedef decl_type* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - redecl_iterator() : Current(nullptr) { } - explicit redecl_iterator(decl_type *C) - : Current(C), Starter(C), PassedFirst(false) { } - - reference operator*() const { return Current; } - pointer operator->() const { return Current; } - - redecl_iterator& operator++() { - assert(Current && "Advancing while iterator has reached end"); - // Sanity check to avoid infinite loop on invalid redecl chain. - if (Current->isFirstDecl()) { - if (PassedFirst) { - assert(0 && "Passed first decl twice, invalid redecl chain!"); - Current = nullptr; - return *this; - } - PassedFirst = true; - } - - // Get either previous decl or latest decl. - decl_type *Next = Current->getNextRedeclaration(); - Current = (Next != Starter) ? Next : nullptr; - return *this; - } - - redecl_iterator operator++(int) { - redecl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(redecl_iterator x, redecl_iterator y) { - return x.Current == y.Current; - } - friend bool operator!=(redecl_iterator x, redecl_iterator y) { - return x.Current != y.Current; - } - }; - - typedef llvm::iterator_range<redecl_iterator> redecl_range; - - /// \brief Returns an iterator range for all the redeclarations of the same - /// decl. It will iterate at least once (when this decl is the only one). - redecl_range redecls() const { - return redecl_range(redecl_iterator(const_cast<decl_type *>( - static_cast<const decl_type *>(this))), - redecl_iterator()); - } - - redecl_iterator redecls_begin() const { return redecls().begin(); } - redecl_iterator redecls_end() const { return redecls().end(); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; -}; - -/// \brief Get the primary declaration for a declaration from an AST file. That -/// will be the first-loaded declaration. -Decl *getPrimaryMergedDecl(Decl *D); - -/// \brief Provides common interface for the Decls that cannot be redeclared, -/// but can be merged if the same declaration is brought in from multiple -/// modules. -template<typename decl_type> -class Mergeable { -public: - Mergeable() {} - - /// \brief Return the first declaration of this declaration or itself if this - /// is the only declaration. - decl_type *getFirstDecl() { - decl_type *D = static_cast<decl_type*>(this); - if (!D->isFromASTFile()) - return D; - return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); - } - - /// \brief Return the first declaration of this declaration or itself if this - /// is the only declaration. - const decl_type *getFirstDecl() const { - const decl_type *D = static_cast<const decl_type*>(this); - if (!D->isFromASTFile()) - return D; - return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); - } - - /// \brief Returns true if this is the first declaration. - bool isFirstDecl() const { return getFirstDecl() == this; } -}; - -} - -#endif diff --git a/include/clang/AST/SelectorLocationsKind.h b/include/clang/AST/SelectorLocationsKind.h deleted file mode 100644 index 6d903f8..0000000 --- a/include/clang/AST/SelectorLocationsKind.h +++ /dev/null @@ -1,83 +0,0 @@ -//===--- SelectorLocationsKind.h - Kind of selector locations ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Describes whether the identifier locations for a selector are "standard" -// or not. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H -#define LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H - -#include "clang/Basic/LLVM.h" - -namespace clang { - class Selector; - class SourceLocation; - class Expr; - class ParmVarDecl; - -/// \brief Whether all locations of the selector identifiers are in a -/// "standard" position. -enum SelectorLocationsKind { - /// \brief Non-standard. - SelLoc_NonStandard = 0, - - /// \brief For nullary selectors, immediately before the end: - /// "[foo release]" / "-(void)release;" - /// Or immediately before the arguments: - /// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y; - SelLoc_StandardNoSpace = 1, - - /// \brief For nullary selectors, immediately before the end: - /// "[foo release]" / "-(void)release;" - /// Or with a space between the arguments: - /// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y; - SelLoc_StandardWithSpace = 2 -}; - -/// \brief Returns true if all \p SelLocs are in a "standard" location. -SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ArrayRef<Expr *> Args, - SourceLocation EndLoc); - -/// \brief Get the "standard" location of a selector identifier, e.g: -/// For nullary selectors, immediately before ']': "[foo release]" -/// -/// \param WithArgSpace if true the standard location is with a space apart -/// before arguments: "[foo first: 1 second: 2]" -/// If false: "[foo first:1 second:2]" -SourceLocation getStandardSelectorLoc(unsigned Index, - Selector Sel, - bool WithArgSpace, - ArrayRef<Expr *> Args, - SourceLocation EndLoc); - -/// \brief Returns true if all \p SelLocs are in a "standard" location. -SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ArrayRef<ParmVarDecl *> Args, - SourceLocation EndLoc); - -/// \brief Get the "standard" location of a selector identifier, e.g: -/// For nullary selectors, immediately before ']': "[foo release]" -/// -/// \param WithArgSpace if true the standard location is with a space apart -/// before arguments: "-(id)first: (int)x second: (int)y;" -/// If false: "-(id)first:(int)x second:(int)y;" -SourceLocation getStandardSelectorLoc(unsigned Index, - Selector Sel, - bool WithArgSpace, - ArrayRef<ParmVarDecl *> Args, - SourceLocation EndLoc); - -} // end namespace clang - -#endif diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h deleted file mode 100644 index e48b7dc..0000000 --- a/include/clang/AST/Stmt.h +++ /dev/null @@ -1,2196 +0,0 @@ -//===--- Stmt.h - Classes for representing statements -----------*- 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 Stmt interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMT_H -#define LLVM_CLANG_AST_STMT_H - -#include "clang/AST/DeclGroup.h" -#include "clang/AST/StmtIterator.h" -#include "clang/Basic/CapturedStmt.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/iterator.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include <string> - -namespace llvm { - class FoldingSetNodeID; -} - -namespace clang { - class ASTContext; - class Attr; - class CapturedDecl; - class Decl; - class Expr; - class IdentifierInfo; - class LabelDecl; - class ParmVarDecl; - class PrinterHelper; - struct PrintingPolicy; - class QualType; - class RecordDecl; - class SourceManager; - class StringLiteral; - class SwitchStmt; - class Token; - class VarDecl; - -//===----------------------------------------------------------------------===// -// AST classes for statements. -//===----------------------------------------------------------------------===// - -/// Stmt - This represents one statement. -/// -class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt { -public: - enum StmtClass { - NoStmtClass = 0, -#define STMT(CLASS, PARENT) CLASS##Class, -#define STMT_RANGE(BASE, FIRST, LAST) \ - first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class, -#define LAST_STMT_RANGE(BASE, FIRST, LAST) \ - first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class -#define ABSTRACT_STMT(STMT) -#include "clang/AST/StmtNodes.inc" - }; - - // Make vanilla 'new' and 'delete' illegal for Stmts. -protected: - void *operator new(size_t bytes) LLVM_NOEXCEPT { - llvm_unreachable("Stmts cannot be allocated with regular 'new'."); - } - void operator delete(void *data) LLVM_NOEXCEPT { - llvm_unreachable("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 ObjCArrayLiteral; // ctor - friend class ObjCDictionaryLiteral; // ctor - friend class ShuffleVectorExpr; // ctor - friend class ParenListExpr; // ctor - friend class CXXUnresolvedConstructExpr; // ctor - friend class CXXDependentScopeMemberExpr; // ctor - friend class OverloadExpr; // ctor - friend class PseudoObjectExpr; // ctor - friend class AtomicExpr; // ctor - unsigned : NumStmtBits; - - unsigned ValueKind : 2; - unsigned ObjectKind : 2; - unsigned TypeDependent : 1; - unsigned ValueDependent : 1; - unsigned InstantiationDependent : 1; - unsigned ContainsUnexpandedParameterPack : 1; - }; - enum { NumExprBits = 16 }; - - class CharacterLiteralBitfields { - friend class CharacterLiteral; - unsigned : NumExprBits; - - unsigned Kind : 2; - }; - - enum APFloatSemantics { - IEEEhalf, - IEEEsingle, - IEEEdouble, - x87DoubleExtended, - IEEEquad, - PPCDoubleDouble - }; - - class FloatingLiteralBitfields { - friend class FloatingLiteral; - unsigned : NumExprBits; - - unsigned Semantics : 3; // Provides semantics for APFloat construction - unsigned IsExact : 1; - }; - - class UnaryExprOrTypeTraitExprBitfields { - friend class UnaryExprOrTypeTraitExpr; - unsigned : NumExprBits; - - unsigned Kind : 2; - unsigned IsType : 1; // true if operand is a type, false if an expression. - }; - - class DeclRefExprBitfields { - friend class DeclRefExpr; - friend class ASTStmtReader; // deserialization - unsigned : NumExprBits; - - unsigned HasQualifier : 1; - unsigned HasTemplateKWAndArgsInfo : 1; - unsigned HasFoundDecl : 1; - unsigned HadMultipleCandidates : 1; - unsigned RefersToEnclosingVariableOrCapture : 1; - }; - - 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; - }; - - class ExprWithCleanupsBitfields { - friend class ExprWithCleanups; - friend class ASTStmtReader; // deserialization - - unsigned : NumExprBits; - - unsigned NumObjects : 32 - NumExprBits; - }; - - class PseudoObjectExprBitfields { - friend class PseudoObjectExpr; - friend class ASTStmtReader; // deserialization - - unsigned : NumExprBits; - - // These don't need to be particularly wide, because they're - // strictly limited by the forms of expressions we permit. - unsigned NumSubExprs : 8; - unsigned ResultIndex : 32 - 8 - NumExprBits; - }; - - class ObjCIndirectCopyRestoreExprBitfields { - friend class ObjCIndirectCopyRestoreExpr; - unsigned : NumExprBits; - - unsigned ShouldCopy : 1; - }; - - class InitListExprBitfields { - friend class InitListExpr; - - unsigned : NumExprBits; - - /// Whether this initializer list originally had a GNU array-range - /// designator in it. This is a temporary marker used by CodeGen. - unsigned HadArrayRangeDesignator : 1; - }; - - class TypeTraitExprBitfields { - friend class TypeTraitExpr; - friend class ASTStmtReader; - friend class ASTStmtWriter; - - unsigned : NumExprBits; - - /// \brief The kind of type trait, which is a value of a TypeTrait enumerator. - unsigned Kind : 8; - - /// \brief If this expression is not value-dependent, this indicates whether - /// the trait evaluated true or false. - unsigned Value : 1; - - /// \brief The number of arguments to this type trait. - unsigned NumArgs : 32 - 8 - 1 - NumExprBits; - }; - - union { - StmtBitfields StmtBits; - CompoundStmtBitfields CompoundStmtBits; - ExprBitfields ExprBits; - CharacterLiteralBitfields CharacterLiteralBits; - FloatingLiteralBitfields FloatingLiteralBits; - UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; - DeclRefExprBitfields DeclRefExprBits; - CastExprBitfields CastExprBits; - CallExprBitfields CallExprBits; - ExprWithCleanupsBitfields ExprWithCleanupsBits; - PseudoObjectExprBitfields PseudoObjectExprBits; - ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; - InitListExprBitfields InitListExprBits; - TypeTraitExprBitfields TypeTraitExprBits; - }; - - friend class ASTStmtReader; - friend class ASTStmtWriter; - -public: - // Only allow allocation of Stmts using the allocator in ASTContext - // or by doing a placement new. - void* operator new(size_t bytes, const ASTContext& C, - unsigned alignment = 8); - - void* operator new(size_t bytes, const ASTContext* C, - unsigned alignment = 8) { - return operator new(bytes, *C, alignment); - } - - void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; } - - void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {} - void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {} - void operator delete(void *, size_t) LLVM_NOEXCEPT {} - void operator delete(void *, void *) LLVM_NOEXCEPT {} - -public: - /// \brief A placeholder type used to construct an empty shell of a - /// type, that will be filled in later (e.g., by some - /// de-serialization). - struct EmptyShell { }; - -protected: - /// Iterator for iterating over Stmt * arrays that contain only Expr * - /// - /// This is needed because AST nodes use Stmt* arrays to store - /// references to children (to be compatible with StmtIterator). - struct ExprIterator - : llvm::iterator_adaptor_base<ExprIterator, Stmt **, - std::random_access_iterator_tag, Expr *> { - ExprIterator() : iterator_adaptor_base(nullptr) {} - ExprIterator(Stmt **I) : iterator_adaptor_base(I) {} - - reference operator*() const { - assert((*I)->getStmtClass() >= firstExprConstant && - (*I)->getStmtClass() <= lastExprConstant); - return *reinterpret_cast<Expr **>(I); - } - }; - - /// Const iterator for iterating over Stmt * arrays that contain only Expr * - struct ConstExprIterator - : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *, - std::random_access_iterator_tag, - const Expr *const> { - ConstExprIterator() : iterator_adaptor_base(nullptr) {} - ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {} - - reference operator*() const { - assert((*I)->getStmtClass() >= firstExprConstant && - (*I)->getStmtClass() <= lastExprConstant); - return *reinterpret_cast<const Expr *const *>(I); - } - }; - -private: - /// \brief Whether statistic collection is enabled. - static bool StatisticsEnabled; - -protected: - /// \brief Construct an empty statement. - explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {} - -public: - Stmt(StmtClass SC) { - static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0, - "Insufficient alignment!"); - StmtBits.sClass = SC; - if (StatisticsEnabled) Stmt::addStmtClass(SC); - } - - StmtClass getStmtClass() const { - 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. - SourceRange getSourceRange() const LLVM_READONLY; - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; - - // global temp stats (until we have a per-module visitor) - static void addStmtClass(const StmtClass s); - static void EnableStatistics(); - static void PrintStats(); - - /// \brief Dumps the specified AST fragment and all subtrees to - /// \c llvm::errs(). - void dump() const; - void dump(SourceManager &SM) const; - void dump(raw_ostream &OS, SourceManager &SM) const; - void dump(raw_ostream &OS) const; - - /// dumpColor - same as dump(), but forces color highlighting. - void dumpColor() const; - - /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST - /// back to its original source language syntax. - void dumpPretty(const ASTContext &Context) const; - void printPretty(raw_ostream &OS, PrinterHelper *Helper, - const PrintingPolicy &Policy, - unsigned Indentation = 0) const; - - /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only - /// works on systems with GraphViz (Mac OS X) or dot+gv installed. - void viewAST() const; - - /// Skip past any implicit AST nodes which might surround this - /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. - Stmt *IgnoreImplicit(); - - /// \brief Skip no-op (attributed, compound) container stmts and skip captured - /// stmt at the top, if \a IgnoreCaptured is true. - Stmt *IgnoreContainers(bool IgnoreCaptured = false); - - const Stmt *stripLabelLikeStatements() const; - Stmt *stripLabelLikeStatements() { - return const_cast<Stmt*>( - const_cast<const Stmt*>(this)->stripLabelLikeStatements()); - } - - /// 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; - - typedef llvm::iterator_range<child_iterator> child_range; - typedef llvm::iterator_range<const_child_iterator> const_child_range; - - child_range children(); - const_child_range children() const { - auto Children = const_cast<Stmt *>(this)->children(); - return const_child_range(Children.begin(), Children.end()); - } - - child_iterator child_begin() { return children().begin(); } - child_iterator child_end() { return children().end(); } - - const_child_iterator child_begin() const { return children().begin(); } - const_child_iterator child_end() const { return children().end(); } - - /// \brief Produce a unique representation of the given statement. - /// - /// \param ID once the profiling operation is complete, will contain - /// the unique representation of the given statement. - /// - /// \param Context the AST context in which the statement resides - /// - /// \param Canonical whether the profile should be based on the canonical - /// representation of this statement (e.g., where non-type template - /// parameters are identified by index/level rather than their - /// declaration pointers) or the exact representation of the statement as - /// written in the source. - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical) const; -}; - -/// DeclStmt - Adaptor class for mixing declarations with statements and -/// expressions. For example, CompoundStmt mixes statements, expressions -/// and declarations (variables, types). Another example is ForStmt, where -/// the first statement can be an expression or a declaration. -/// -class DeclStmt : public Stmt { - DeclGroupRef DG; - SourceLocation StartLoc, EndLoc; - -public: - DeclStmt(DeclGroupRef dg, SourceLocation startLoc, - SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), - StartLoc(startLoc), EndLoc(endLoc) {} - - /// \brief Build an empty declaration statement. - explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } - - /// isSingleDecl - This method returns true if this DeclStmt refers - /// to a single Decl. - bool isSingleDecl() const { - return DG.isSingleDecl(); - } - - const Decl *getSingleDecl() const { return DG.getSingleDecl(); } - Decl *getSingleDecl() { return DG.getSingleDecl(); } - - const DeclGroupRef getDeclGroup() const { return DG; } - DeclGroupRef getDeclGroup() { return DG; } - void setDeclGroup(DeclGroupRef DGR) { DG = DGR; } - - SourceLocation getStartLoc() const { return StartLoc; } - void setStartLoc(SourceLocation L) { StartLoc = L; } - SourceLocation getEndLoc() const { return EndLoc; } - void setEndLoc(SourceLocation L) { EndLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return StartLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DeclStmtClass; - } - - // Iterators over subexpressions. - 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; - typedef llvm::iterator_range<decl_iterator> decl_range; - typedef llvm::iterator_range<const_decl_iterator> decl_const_range; - - decl_range decls() { return decl_range(decl_begin(), decl_end()); } - decl_const_range decls() const { - return decl_const_range(decl_begin(), decl_end()); - } - decl_iterator decl_begin() { return DG.begin(); } - decl_iterator decl_end() { return DG.end(); } - const_decl_iterator decl_begin() const { return DG.begin(); } - const_decl_iterator decl_end() const { return DG.end(); } - - typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator; - reverse_decl_iterator decl_rbegin() { - return reverse_decl_iterator(decl_end()); - } - reverse_decl_iterator decl_rend() { - return reverse_decl_iterator(decl_begin()); - } -}; - -/// NullStmt - This is the null statement ";": C99 6.8.3p3. -/// -class NullStmt : public Stmt { - SourceLocation SemiLoc; - - /// \brief True if the null statement was preceded by an empty macro, e.g: - /// @code - /// #define CALL(x) - /// CALL(0); - /// @endcode - bool HasLeadingEmptyMacro; -public: - NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false) - : Stmt(NullStmtClass), SemiLoc(L), - HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} - - /// \brief Build an empty null statement. - explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty), - HasLeadingEmptyMacro(false) { } - - SourceLocation getSemiLoc() const { return SemiLoc; } - void setSemiLoc(SourceLocation L) { SemiLoc = L; } - - bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; } - - SourceLocation getLocStart() const LLVM_READONLY { return SemiLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SemiLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == NullStmtClass; - } - - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - - friend class ASTStmtReader; - friend class ASTStmtWriter; -}; - -/// CompoundStmt - This represents a group of statements like { stmt stmt }. -/// -class CompoundStmt : public Stmt { - Stmt** Body; - SourceLocation LBraceLoc, RBraceLoc; - - friend class ASTStmtReader; - -public: - CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, - SourceLocation LB, SourceLocation RB); - - // \brief Build an empty compound statement with a location. - explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) { - CompoundStmtBits.NumStmts = 0; - } - - // \brief Build an empty compound statement. - explicit CompoundStmt(EmptyShell Empty) - : Stmt(CompoundStmtClass, Empty), Body(nullptr) { - CompoundStmtBits.NumStmts = 0; - } - - void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts); - - bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } - unsigned size() const { return CompoundStmtBits.NumStmts; } - - typedef Stmt** body_iterator; - typedef llvm::iterator_range<body_iterator> body_range; - - body_range body() { return body_range(body_begin(), body_end()); } - body_iterator body_begin() { return Body; } - body_iterator body_end() { return Body + size(); } - Stmt *body_front() { return !body_empty() ? Body[0] : nullptr; } - Stmt *body_back() { return !body_empty() ? Body[size()-1] : nullptr; } - - void setLastStmt(Stmt *S) { - assert(!body_empty() && "setLastStmt"); - Body[size()-1] = S; - } - - typedef Stmt* const * const_body_iterator; - typedef llvm::iterator_range<const_body_iterator> body_const_range; - - body_const_range body() const { - return body_const_range(body_begin(), body_end()); - } - const_body_iterator body_begin() const { return Body; } - const_body_iterator body_end() const { return Body + size(); } - const Stmt *body_front() const { - return !body_empty() ? Body[0] : nullptr; - } - const Stmt *body_back() const { - return !body_empty() ? Body[size() - 1] : nullptr; - } - - typedef std::reverse_iterator<body_iterator> reverse_body_iterator; - reverse_body_iterator body_rbegin() { - return reverse_body_iterator(body_end()); - } - reverse_body_iterator body_rend() { - return reverse_body_iterator(body_begin()); - } - - typedef std::reverse_iterator<const_body_iterator> - const_reverse_body_iterator; - - const_reverse_body_iterator body_rbegin() const { - return const_reverse_body_iterator(body_end()); - } - - const_reverse_body_iterator body_rend() const { - return const_reverse_body_iterator(body_begin()); - } - - SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; } - - SourceLocation getLBracLoc() const { return LBraceLoc; } - SourceLocation getRBracLoc() const { return RBraceLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CompoundStmtClass; - } - - // Iterators - child_range children() { - return child_range(Body, Body + CompoundStmtBits.NumStmts); - } - - const_child_range children() const { - return const_child_range(child_iterator(Body), - child_iterator(Body + CompoundStmtBits.NumStmts)); - } -}; - -// SwitchCase is the base class for CaseStmt and DefaultStmt, -class SwitchCase : public Stmt { -protected: - // A pointer to the following CaseStmt or DefaultStmt class, - // used by SwitchStmt. - SwitchCase *NextSwitchCase; - SourceLocation KeywordLoc; - SourceLocation ColonLoc; - - SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc) - : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) { - } - - SwitchCase(StmtClass SC, EmptyShell) - : Stmt(SC), NextSwitchCase(nullptr) {} - -public: - const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } - - SwitchCase *getNextSwitchCase() { return NextSwitchCase; } - - void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } - - SourceLocation getKeywordLoc() const { return KeywordLoc; } - void setKeywordLoc(SourceLocation L) { KeywordLoc = L; } - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } - - Stmt *getSubStmt(); - const Stmt *getSubStmt() const { - return const_cast<SwitchCase*>(this)->getSubStmt(); - } - - SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CaseStmtClass || - T->getStmtClass() == DefaultStmtClass; - } -}; - -class CaseStmt : public SwitchCase { - SourceLocation EllipsisLoc; - enum { LHS, RHS, SUBSTMT, END_EXPR }; - Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for - // GNU "case 1 ... 4" extension -public: - CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, - SourceLocation ellipsisLoc, SourceLocation colonLoc) - : SwitchCase(CaseStmtClass, caseLoc, colonLoc) { - SubExprs[SUBSTMT] = nullptr; - SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); - SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); - EllipsisLoc = ellipsisLoc; - } - - /// \brief Build an empty switch case statement. - explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { } - - SourceLocation getCaseLoc() const { return KeywordLoc; } - void setCaseLoc(SourceLocation L) { KeywordLoc = L; } - SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; } - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } - - Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); } - Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); } - Stmt *getSubStmt() { return SubExprs[SUBSTMT]; } - - const Expr *getLHS() const { - return reinterpret_cast<const Expr*>(SubExprs[LHS]); - } - const Expr *getRHS() const { - return reinterpret_cast<const Expr*>(SubExprs[RHS]); - } - const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } - - void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } - void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); } - void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } - - SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - // Handle deeply nested case statements with iteration instead of recursion. - const CaseStmt *CS = this; - while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) - CS = CS2; - - return CS->getSubStmt()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CaseStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[END_EXPR]); - } -}; - -class DefaultStmt : public SwitchCase { - Stmt* SubStmt; -public: - DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : - SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {} - - /// \brief Build an empty default statement. - explicit DefaultStmt(EmptyShell Empty) - : SwitchCase(DefaultStmtClass, Empty) { } - - Stmt *getSubStmt() { return SubStmt; } - const Stmt *getSubStmt() const { return SubStmt; } - void setSubStmt(Stmt *S) { SubStmt = S; } - - SourceLocation getDefaultLoc() const { return KeywordLoc; } - void setDefaultLoc(SourceLocation L) { KeywordLoc = L; } - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DefaultStmtClass; - } - - // Iterators - child_range children() { return child_range(&SubStmt, &SubStmt+1); } -}; - -inline SourceLocation SwitchCase::getLocEnd() const { - if (const CaseStmt *CS = dyn_cast<CaseStmt>(this)) - return CS->getLocEnd(); - return cast<DefaultStmt>(this)->getLocEnd(); -} - -/// LabelStmt - Represents a label, which has a substatement. For example: -/// foo: return; -/// -class LabelStmt : public Stmt { - SourceLocation IdentLoc; - LabelDecl *TheDecl; - Stmt *SubStmt; - -public: - LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt) - : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) { - static_assert(sizeof(LabelStmt) == - 2 * sizeof(SourceLocation) + 2 * sizeof(void *), - "LabelStmt too big"); - } - - // \brief Build an empty label statement. - explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } - - SourceLocation getIdentLoc() const { return IdentLoc; } - 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; } - - SourceLocation getLocStart() const LLVM_READONLY { return IdentLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} - - child_range children() { return child_range(&SubStmt, &SubStmt+1); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == LabelStmtClass; - } -}; - - -/// \brief Represents an attribute applied to a statement. -/// -/// Represents an attribute applied to a statement. For example: -/// [[omp::for(...)]] for (...) { ... } -/// -class AttributedStmt : public Stmt { - Stmt *SubStmt; - SourceLocation AttrLoc; - unsigned NumAttrs; - - friend class ASTStmtReader; - - AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) - : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), - NumAttrs(Attrs.size()) { - std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr()); - } - - explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) - : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { - std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr); - } - - const Attr *const *getAttrArrayPtr() const { - return reinterpret_cast<const Attr *const *>(this + 1); - } - const Attr **getAttrArrayPtr() { - return reinterpret_cast<const Attr **>(this + 1); - } - -public: - static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, - ArrayRef<const Attr*> Attrs, Stmt *SubStmt); - // \brief Build an empty attributed statement. - static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); - - SourceLocation getAttrLoc() const { return AttrLoc; } - ArrayRef<const Attr*> getAttrs() const { - return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs); - } - Stmt *getSubStmt() { return SubStmt; } - const Stmt *getSubStmt() const { return SubStmt; } - - SourceLocation getLocStart() const LLVM_READONLY { return AttrLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} - - child_range children() { return child_range(&SubStmt, &SubStmt + 1); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == AttributedStmtClass; - } -}; - - -/// IfStmt - This represents an if/then/else. -/// -class IfStmt : public Stmt { - enum { VAR, COND, THEN, ELSE, END_EXPR }; - Stmt* SubExprs[END_EXPR]; - - SourceLocation IfLoc; - SourceLocation ElseLoc; - -public: - IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, - Stmt *then, SourceLocation EL = SourceLocation(), - Stmt *elsev = nullptr); - - /// \brief Build an empty if/then/else statement - explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } - - /// \brief Retrieve the variable declared in this "if" statement, if any. - /// - /// In the following example, "x" is the condition variable. - /// \code - /// if (int x = foo()) { - /// printf("x is %d", x); - /// } - /// \endcode - VarDecl *getConditionVariable() const; - void setConditionVariable(const ASTContext &C, VarDecl *V); - - /// If this IfStmt has a condition variable, return the faux DeclStmt - /// associated with the creation of that condition variable. - const DeclStmt *getConditionVariableDeclStmt() const { - return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); - } - - const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } - const Stmt *getThen() const { return SubExprs[THEN]; } - void setThen(Stmt *S) { SubExprs[THEN] = S; } - const Stmt *getElse() const { return SubExprs[ELSE]; } - void setElse(Stmt *S) { SubExprs[ELSE] = S; } - - Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } - Stmt *getThen() { return SubExprs[THEN]; } - Stmt *getElse() { return SubExprs[ELSE]; } - - SourceLocation getIfLoc() const { return IfLoc; } - void setIfLoc(SourceLocation L) { IfLoc = L; } - SourceLocation getElseLoc() const { return ElseLoc; } - void setElseLoc(SourceLocation L) { ElseLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - if (SubExprs[ELSE]) - return SubExprs[ELSE]->getLocEnd(); - else - return 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; - } -}; - -/// SwitchStmt - This represents a 'switch' stmt. -/// -class SwitchStmt : public Stmt { - SourceLocation SwitchLoc; - enum { VAR, COND, BODY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; - // This points to a linked list of case and default statements and, if the - // SwitchStmt is a switch on an enum value, records whether all the enum - // values were covered by CaseStmts. The coverage information value is meant - // to be a hint for possible clients. - llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase; - -public: - SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond); - - /// \brief Build a empty switch statement. - explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } - - /// \brief Retrieve the variable declared in this "switch" statement, if any. - /// - /// In the following example, "x" is the condition variable. - /// \code - /// switch (int x = foo()) { - /// case 0: break; - /// // ... - /// } - /// \endcode - VarDecl *getConditionVariable() const; - void setConditionVariable(const ASTContext &C, VarDecl *V); - - /// If this SwitchStmt has a condition variable, return the faux DeclStmt - /// associated with the creation of that condition variable. - const DeclStmt *getConditionVariableDeclStmt() const { - return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); - } - - const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} - const Stmt *getBody() const { return SubExprs[BODY]; } - const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); } - - Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);} - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } - Stmt *getBody() { return SubExprs[BODY]; } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); } - - /// \brief Set the case list for this switch statement. - void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); } - - SourceLocation getSwitchLoc() const { return SwitchLoc; } - void setSwitchLoc(SourceLocation L) { SwitchLoc = L; } - - void setBody(Stmt *S, SourceLocation SL) { - SubExprs[BODY] = S; - SwitchLoc = SL; - } - void addSwitchCase(SwitchCase *SC) { - assert(!SC->getNextSwitchCase() - && "case/default already added to a switch"); - SC->setNextSwitchCase(FirstCase.getPointer()); - FirstCase.setPointer(SC); - } - - /// 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() { FirstCase.setInt(true); } - - /// Returns true if the SwitchStmt is a switch of an enum value and all cases - /// have been explicitly covered. - bool isAllEnumCasesCovered() const { return FirstCase.getInt(); } - - SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd(); - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SwitchStmtClass; - } -}; - - -/// WhileStmt - This represents a 'while' stmt. -/// -class WhileStmt : public Stmt { - SourceLocation WhileLoc; - enum { VAR, COND, BODY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; -public: - WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, - SourceLocation WL); - - /// \brief Build an empty while statement. - explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } - - /// \brief Retrieve the variable declared in this "while" statement, if any. - /// - /// In the following example, "x" is the condition variable. - /// \code - /// while (int x = random()) { - /// // ... - /// } - /// \endcode - VarDecl *getConditionVariable() const; - void setConditionVariable(const ASTContext &C, VarDecl *V); - - /// If this WhileStmt has a condition variable, return the faux DeclStmt - /// associated with the creation of that condition variable. - const DeclStmt *getConditionVariableDeclStmt() const { - return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); - } - - Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } - const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } - Stmt *getBody() { return SubExprs[BODY]; } - const Stmt *getBody() const { return SubExprs[BODY]; } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - - SourceLocation getWhileLoc() const { return WhileLoc; } - void setWhileLoc(SourceLocation L) { WhileLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == WhileStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } -}; - -/// DoStmt - This represents a 'do/while' stmt. -/// -class DoStmt : public Stmt { - SourceLocation DoLoc; - enum { BODY, COND, END_EXPR }; - Stmt* SubExprs[END_EXPR]; - SourceLocation WhileLoc; - SourceLocation RParenLoc; // Location of final ')' in do stmt condition. - -public: - DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL, - SourceLocation RP) - : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) { - SubExprs[COND] = reinterpret_cast<Stmt*>(cond); - SubExprs[BODY] = body; - } - - /// \brief Build an empty do-while statement. - explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } - - Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } - const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } - Stmt *getBody() { return SubExprs[BODY]; } - const Stmt *getBody() const { return SubExprs[BODY]; } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - - SourceLocation getDoLoc() const { return DoLoc; } - void setDoLoc(SourceLocation L) { DoLoc = L; } - SourceLocation getWhileLoc() const { return WhileLoc; } - void setWhileLoc(SourceLocation L) { WhileLoc = L; } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return DoLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DoStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } -}; - - -/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of -/// the init/cond/inc parts of the ForStmt will be null if they were not -/// specified in the source. -/// -class ForStmt : public Stmt { - SourceLocation ForLoc; - enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. - SourceLocation LParenLoc, RParenLoc; - -public: - ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, - Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, - SourceLocation RP); - - /// \brief Build an empty for statement. - explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } - - Stmt *getInit() { return SubExprs[INIT]; } - - /// \brief Retrieve the variable declared in this "for" statement, if any. - /// - /// In the following example, "y" is the condition variable. - /// \code - /// for (int x = random(); int y = mangle(x); ++x) { - /// // ... - /// } - /// \endcode - VarDecl *getConditionVariable() const; - void setConditionVariable(const ASTContext &C, VarDecl *V); - - /// If this ForStmt has a condition variable, return the faux DeclStmt - /// associated with the creation of that condition variable. - const DeclStmt *getConditionVariableDeclStmt() const { - return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]); - } - - Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } - Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } - Stmt *getBody() { return SubExprs[BODY]; } - - const Stmt *getInit() const { return SubExprs[INIT]; } - const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} - const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); } - const Stmt *getBody() const { return SubExprs[BODY]; } - - void setInit(Stmt *S) { SubExprs[INIT] = S; } - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } - void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - - SourceLocation getForLoc() const { return ForLoc; } - void setForLoc(SourceLocation L) { ForLoc = L; } - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ForStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); - } -}; - -/// GotoStmt - This represents a direct goto. -/// -class GotoStmt : public Stmt { - LabelDecl *Label; - SourceLocation GotoLoc; - SourceLocation LabelLoc; -public: - 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) { } - - 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; } - - SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == GotoStmtClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// IndirectGotoStmt - This represents an indirect goto. -/// -class IndirectGotoStmt : public Stmt { - SourceLocation GotoLoc; - SourceLocation StarLoc; - Stmt *Target; -public: - IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, - Expr *target) - : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc), - Target((Stmt*)target) {} - - /// \brief Build an empty indirect goto statement. - explicit IndirectGotoStmt(EmptyShell Empty) - : Stmt(IndirectGotoStmtClass, Empty) { } - - void setGotoLoc(SourceLocation L) { GotoLoc = L; } - SourceLocation getGotoLoc() const { return GotoLoc; } - void setStarLoc(SourceLocation L) { StarLoc = L; } - SourceLocation getStarLoc() const { return StarLoc; } - - Expr *getTarget() { return reinterpret_cast<Expr*>(Target); } - const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);} - void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); } - - /// getConstantTarget - Returns the fixed target of this indirect - /// goto, if one exists. - LabelDecl *getConstantTarget(); - const LabelDecl *getConstantTarget() const { - return const_cast<IndirectGotoStmt*>(this)->getConstantTarget(); - } - - SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Target->getLocEnd(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == IndirectGotoStmtClass; - } - - // Iterators - child_range children() { return child_range(&Target, &Target+1); } -}; - - -/// ContinueStmt - This represents a continue. -/// -class ContinueStmt : public Stmt { - SourceLocation ContinueLoc; -public: - ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} - - /// \brief Build an empty continue statement. - explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } - - SourceLocation getContinueLoc() const { return ContinueLoc; } - void setContinueLoc(SourceLocation L) { ContinueLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return ContinueLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return ContinueLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ContinueStmtClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// BreakStmt - This represents a break. -/// -class BreakStmt : public Stmt { - SourceLocation BreakLoc; - -public: - BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) { - static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation), - "BreakStmt too large"); - } - - /// \brief Build an empty break statement. - explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } - - SourceLocation getBreakLoc() const { return BreakLoc; } - void setBreakLoc(SourceLocation L) { BreakLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return BreakLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return BreakLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BreakStmtClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - - -/// ReturnStmt - This represents a return, optionally of an expression: -/// return; -/// return 4; -/// -/// Note that GCC allows return with no argument in a function declared to -/// return a value, and it allows returning a value in functions declared to -/// return void. We explicitly model this in the AST, which means you can't -/// depend on the return type of the function and the presence of an argument. -/// -class ReturnStmt : public Stmt { - SourceLocation RetLoc; - Stmt *RetExpr; - const VarDecl *NRVOCandidate; - -public: - explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {} - - ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) - : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E), - NRVOCandidate(NRVOCandidate) {} - - /// \brief Build an empty return expression. - explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } - - const Expr *getRetValue() const; - Expr *getRetValue(); - void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); } - - SourceLocation getReturnLoc() const { return RetLoc; } - void setReturnLoc(SourceLocation L) { RetLoc = L; } - - /// \brief Retrieve the variable that might be used for the named return - /// value optimization. - /// - /// The optimization itself can only be performed if the variable is - /// also marked as an NRVO object. - const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } - void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } - - SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return RetExpr ? RetExpr->getLocEnd() : RetLoc; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ReturnStmtClass; - } - - // Iterators - child_range children() { - if (RetExpr) return child_range(&RetExpr, &RetExpr+1); - return child_range(child_iterator(), child_iterator()); - } -}; - -/// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt. -/// -class AsmStmt : public Stmt { -protected: - SourceLocation AsmLoc; - /// \brief True if the assembly statement does not have any input or output - /// operands. - bool IsSimple; - - /// \brief If true, treat this inline assembly as having side effects. - /// This assembly statement should not be optimized, deleted or moved. - bool IsVolatile; - - unsigned NumOutputs; - unsigned NumInputs; - unsigned NumClobbers; - - Stmt **Exprs; - - AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile, - unsigned numoutputs, unsigned numinputs, unsigned numclobbers) : - Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), - NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { } - - friend class ASTStmtReader; - -public: - /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(StmtClass SC, EmptyShell Empty) : - Stmt(SC, Empty), Exprs(nullptr) { } - - SourceLocation getAsmLoc() const { return AsmLoc; } - void setAsmLoc(SourceLocation L) { AsmLoc = L; } - - bool isSimple() const { return IsSimple; } - void setSimple(bool V) { IsSimple = V; } - - bool isVolatile() const { return IsVolatile; } - void setVolatile(bool V) { IsVolatile = V; } - - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } - - //===--- Asm String Analysis ---===// - - /// Assemble final IR asm string. - std::string generateAsmString(const ASTContext &C) const; - - //===--- Output operands ---===// - - unsigned getNumOutputs() const { return NumOutputs; } - - /// getOutputConstraint - Return the constraint string for the specified - /// output operand. All output constraints are known to be non-empty (either - /// '=' or '+'). - StringRef getOutputConstraint(unsigned i) const; - - /// isOutputPlusConstraint - Return true if the specified output constraint - /// is a "+" constraint (which is both an input and an output) or false if it - /// is an "=" constraint (just an output). - bool isOutputPlusConstraint(unsigned i) const { - return getOutputConstraint(i)[0] == '+'; - } - - const Expr *getOutputExpr(unsigned i) const; - - /// getNumPlusOperands - Return the number of output operands that have a "+" - /// constraint. - unsigned getNumPlusOperands() const; - - //===--- Input operands ---===// - - unsigned getNumInputs() const { return NumInputs; } - - /// getInputConstraint - Return the specified input constraint. Unlike output - /// constraints, these can be empty. - StringRef getInputConstraint(unsigned i) const; - - const Expr *getInputExpr(unsigned i) const; - - //===--- Other ---===// - - unsigned getNumClobbers() const { return NumClobbers; } - StringRef getClobber(unsigned i) const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == GCCAsmStmtClass || - T->getStmtClass() == MSAsmStmtClass; - } - - // Input expr iterators. - - typedef ExprIterator inputs_iterator; - typedef ConstExprIterator const_inputs_iterator; - typedef llvm::iterator_range<inputs_iterator> inputs_range; - typedef llvm::iterator_range<const_inputs_iterator> inputs_const_range; - - inputs_iterator begin_inputs() { - return &Exprs[0] + NumOutputs; - } - - inputs_iterator end_inputs() { - return &Exprs[0] + NumOutputs + NumInputs; - } - - inputs_range inputs() { return inputs_range(begin_inputs(), end_inputs()); } - - const_inputs_iterator begin_inputs() const { - return &Exprs[0] + NumOutputs; - } - - const_inputs_iterator end_inputs() const { - return &Exprs[0] + NumOutputs + NumInputs; - } - - inputs_const_range inputs() const { - return inputs_const_range(begin_inputs(), end_inputs()); - } - - // Output expr iterators. - - typedef ExprIterator outputs_iterator; - typedef ConstExprIterator const_outputs_iterator; - typedef llvm::iterator_range<outputs_iterator> outputs_range; - typedef llvm::iterator_range<const_outputs_iterator> outputs_const_range; - - outputs_iterator begin_outputs() { - return &Exprs[0]; - } - outputs_iterator end_outputs() { - return &Exprs[0] + NumOutputs; - } - outputs_range outputs() { - return outputs_range(begin_outputs(), end_outputs()); - } - - const_outputs_iterator begin_outputs() const { - return &Exprs[0]; - } - const_outputs_iterator end_outputs() const { - return &Exprs[0] + NumOutputs; - } - outputs_const_range outputs() const { - return outputs_const_range(begin_outputs(), end_outputs()); - } - - child_range children() { - return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); - } -}; - -/// This represents a GCC inline-assembly statement extension. -/// -class GCCAsmStmt : public AsmStmt { - SourceLocation RParenLoc; - StringLiteral *AsmStr; - - // FIXME: If we wanted to, we could allocate all of these in one big array. - StringLiteral **Constraints; - StringLiteral **Clobbers; - IdentifierInfo **Names; - - friend class ASTStmtReader; - -public: - GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, - bool isvolatile, unsigned numoutputs, unsigned numinputs, - IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, - StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, SourceLocation rparenloc); - - /// \brief Build an empty inline-assembly statement. - explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), - Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { } - - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - //===--- Asm String Analysis ---===// - - const StringLiteral *getAsmString() const { return AsmStr; } - StringLiteral *getAsmString() { return AsmStr; } - void setAsmString(StringLiteral *E) { AsmStr = E; } - - /// AsmStringPiece - this is part of a decomposed asm string specification - /// (for use with the AnalyzeAsmString function below). An asm string is - /// considered to be a concatenation of these parts. - class AsmStringPiece { - public: - enum Kind { - String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". - Operand // Operand reference, with optional modifier %c4. - }; - private: - Kind MyKind; - std::string Str; - unsigned OperandNo; - - // Source range for operand references. - CharSourceRange Range; - public: - AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} - AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin, - SourceLocation End) - : MyKind(Operand), Str(S), OperandNo(OpNo), - Range(CharSourceRange::getCharRange(Begin, End)) { - } - - bool isString() const { return MyKind == String; } - bool isOperand() const { return MyKind == Operand; } - - const std::string &getString() const { - return Str; - } - - unsigned getOperandNo() const { - assert(isOperand()); - return OperandNo; - } - - CharSourceRange getRange() const { - assert(isOperand() && "Range is currently used only for Operands."); - return Range; - } - - /// getModifier - Get the modifier for this operand, if present. This - /// returns '\0' if there was no modifier. - char getModifier() const; - }; - - /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing - /// it into pieces. If the asm string is erroneous, emit errors and return - /// true, otherwise return false. This handles canonicalization and - /// translation of strings from GCC syntax to LLVM IR syntax, and handles - //// flattening of named references like %[foo] to Operand AsmStringPiece's. - unsigned AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> &Pieces, - const ASTContext &C, unsigned &DiagOffs) const; - - /// Assemble final IR asm string. - std::string generateAsmString(const ASTContext &C) const; - - //===--- Output operands ---===// - - IdentifierInfo *getOutputIdentifier(unsigned i) const { - return Names[i]; - } - - StringRef getOutputName(unsigned i) const { - if (IdentifierInfo *II = getOutputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - - StringRef getOutputConstraint(unsigned i) const; - - const StringLiteral *getOutputConstraintLiteral(unsigned i) const { - return Constraints[i]; - } - StringLiteral *getOutputConstraintLiteral(unsigned i) { - return Constraints[i]; - } - - Expr *getOutputExpr(unsigned i); - - const Expr *getOutputExpr(unsigned i) const { - return const_cast<GCCAsmStmt*>(this)->getOutputExpr(i); - } - - //===--- Input operands ---===// - - IdentifierInfo *getInputIdentifier(unsigned i) const { - return Names[i + NumOutputs]; - } - - StringRef getInputName(unsigned i) const { - if (IdentifierInfo *II = getInputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - - StringRef getInputConstraint(unsigned i) const; - - const StringLiteral *getInputConstraintLiteral(unsigned i) const { - return Constraints[i + NumOutputs]; - } - StringLiteral *getInputConstraintLiteral(unsigned i) { - return Constraints[i + NumOutputs]; - } - - Expr *getInputExpr(unsigned i); - void setInputExpr(unsigned i, Expr *E); - - const Expr *getInputExpr(unsigned i) const { - return const_cast<GCCAsmStmt*>(this)->getInputExpr(i); - } - -private: - void setOutputsAndInputsAndClobbers(const ASTContext &C, - IdentifierInfo **Names, - StringLiteral **Constraints, - Stmt **Exprs, - unsigned NumOutputs, - unsigned NumInputs, - StringLiteral **Clobbers, - unsigned NumClobbers); -public: - - //===--- Other ---===// - - /// getNamedOperand - Given a symbolic operand reference like %[foo], - /// translate this into a numeric value needed to reference the same operand. - /// This returns -1 if the operand name is invalid. - int getNamedOperand(StringRef SymbolicName) const; - - StringRef getClobber(unsigned i) const; - StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; } - const StringLiteral *getClobberStringLiteral(unsigned i) const { - return Clobbers[i]; - } - - SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == GCCAsmStmtClass; - } -}; - -/// This represents a Microsoft inline-assembly statement extension. -/// -class MSAsmStmt : public AsmStmt { - SourceLocation LBraceLoc, EndLoc; - StringRef AsmStr; - - unsigned NumAsmToks; - - Token *AsmToks; - StringRef *Constraints; - StringRef *Clobbers; - - friend class ASTStmtReader; - -public: - MSAsmStmt(const ASTContext &C, SourceLocation asmloc, - SourceLocation lbraceloc, bool issimple, bool isvolatile, - ArrayRef<Token> asmtoks, unsigned numoutputs, unsigned numinputs, - ArrayRef<StringRef> constraints, - ArrayRef<Expr*> exprs, StringRef asmstr, - ArrayRef<StringRef> clobbers, SourceLocation endloc); - - /// \brief Build an empty MS-style inline-assembly statement. - explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty), - NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { } - - SourceLocation getLBraceLoc() const { return LBraceLoc; } - void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } - SourceLocation getEndLoc() const { return EndLoc; } - void setEndLoc(SourceLocation L) { EndLoc = L; } - - bool hasBraces() const { return LBraceLoc.isValid(); } - - unsigned getNumAsmToks() { return NumAsmToks; } - Token *getAsmToks() { return AsmToks; } - - //===--- Asm String Analysis ---===// - StringRef getAsmString() const { return AsmStr; } - - /// Assemble final IR asm string. - std::string generateAsmString(const ASTContext &C) const; - - //===--- Output operands ---===// - - StringRef getOutputConstraint(unsigned i) const { - assert(i < NumOutputs); - return Constraints[i]; - } - - Expr *getOutputExpr(unsigned i); - - const Expr *getOutputExpr(unsigned i) const { - return const_cast<MSAsmStmt*>(this)->getOutputExpr(i); - } - - //===--- Input operands ---===// - - StringRef getInputConstraint(unsigned i) const { - assert(i < NumInputs); - return Constraints[i + NumOutputs]; - } - - Expr *getInputExpr(unsigned i); - void setInputExpr(unsigned i, Expr *E); - - const Expr *getInputExpr(unsigned i) const { - return const_cast<MSAsmStmt*>(this)->getInputExpr(i); - } - - //===--- Other ---===// - - ArrayRef<StringRef> getAllConstraints() const { - return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); - } - ArrayRef<StringRef> getClobbers() const { - return llvm::makeArrayRef(Clobbers, NumClobbers); - } - ArrayRef<Expr*> getAllExprs() const { - return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs), - NumInputs + NumOutputs); - } - - StringRef getClobber(unsigned i) const { return getClobbers()[i]; } - -private: - void initialize(const ASTContext &C, StringRef AsmString, - ArrayRef<Token> AsmToks, ArrayRef<StringRef> Constraints, - ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers); -public: - - SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == MSAsmStmtClass; - } - - child_range children() { - return child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]); - } -}; - -class SEHExceptStmt : public Stmt { - SourceLocation Loc; - Stmt *Children[2]; - - enum { FILTER_EXPR, BLOCK }; - - SEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block); - - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { } - -public: - static SEHExceptStmt* Create(const ASTContext &C, - SourceLocation ExceptLoc, - Expr *FilterExpr, - Stmt *Block); - - SourceLocation getLocStart() const LLVM_READONLY { return getExceptLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - SourceLocation getExceptLoc() const { return Loc; } - SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } - - Expr *getFilterExpr() const { - return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); - } - - CompoundStmt *getBlock() const { - return cast<CompoundStmt>(Children[BLOCK]); - } - - child_range children() { - return child_range(Children,Children+2); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SEHExceptStmtClass; - } - -}; - -class SEHFinallyStmt : public Stmt { - SourceLocation Loc; - Stmt *Block; - - SEHFinallyStmt(SourceLocation Loc, - Stmt *Block); - - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { } - -public: - static SEHFinallyStmt* Create(const ASTContext &C, - SourceLocation FinallyLoc, - Stmt *Block); - - SourceLocation getLocStart() const LLVM_READONLY { return getFinallyLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - SourceLocation getFinallyLoc() const { return Loc; } - SourceLocation getEndLoc() const { return Block->getLocEnd(); } - - CompoundStmt *getBlock() const { return cast<CompoundStmt>(Block); } - - child_range children() { - return child_range(&Block,&Block+1); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SEHFinallyStmtClass; - } - -}; - -class SEHTryStmt : public Stmt { - bool IsCXXTry; - SourceLocation TryLoc; - Stmt *Children[2]; - - enum { TRY = 0, HANDLER = 1 }; - - SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler); - - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } - -public: - static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, - SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler); - - SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - SourceLocation getTryLoc() const { return TryLoc; } - SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } - - bool getIsCXXTry() const { return IsCXXTry; } - - CompoundStmt* getTryBlock() const { - return cast<CompoundStmt>(Children[TRY]); - } - - Stmt *getHandler() const { return Children[HANDLER]; } - - /// Returns 0 if not defined - SEHExceptStmt *getExceptHandler() const; - SEHFinallyStmt *getFinallyHandler() const; - - child_range children() { - return child_range(Children,Children+2); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SEHTryStmtClass; - } -}; - -/// Represents a __leave statement. -/// -class SEHLeaveStmt : public Stmt { - SourceLocation LeaveLoc; -public: - explicit SEHLeaveStmt(SourceLocation LL) - : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} - - /// \brief Build an empty __leave statement. - explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { } - - SourceLocation getLeaveLoc() const { return LeaveLoc; } - void setLeaveLoc(SourceLocation L) { LeaveLoc = L; } - - SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == SEHLeaveStmtClass; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } -}; - -/// \brief This captures a statement into a function. For example, the following -/// pragma annotated compound statement can be represented as a CapturedStmt, -/// and this compound statement is the body of an anonymous outlined function. -/// @code -/// #pragma omp parallel -/// { -/// compute(); -/// } -/// @endcode -class CapturedStmt : public Stmt { -public: - /// \brief The different capture forms: by 'this', by reference, capture for - /// variable-length array type etc. - enum VariableCaptureKind { - VCK_This, - VCK_ByRef, - VCK_ByCopy, - VCK_VLAType, - }; - - /// \brief Describes the capture of either a variable, or 'this', or - /// variable-length array type. - class Capture { - llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind; - SourceLocation Loc; - - public: - /// \brief Create a new capture. - /// - /// \param Loc The source location associated with this capture. - /// - /// \param Kind The kind of capture (this, ByRef, ...). - /// - /// \param Var The variable being captured, or null if capturing this. - /// - Capture(SourceLocation Loc, VariableCaptureKind Kind, - VarDecl *Var = nullptr); - - /// \brief Determine the kind of capture. - VariableCaptureKind getCaptureKind() const; - - /// \brief Retrieve the source location at which the variable or 'this' was - /// first used. - SourceLocation getLocation() const { return Loc; } - - /// \brief Determine whether this capture handles the C++ 'this' pointer. - bool capturesThis() const { return getCaptureKind() == VCK_This; } - - /// \brief Determine whether this capture handles a variable (by reference). - bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; } - - /// \brief Determine whether this capture handles a variable by copy. - bool capturesVariableByCopy() const { - return getCaptureKind() == VCK_ByCopy; - } - - /// \brief Determine whether this capture handles a variable-length array - /// type. - bool capturesVariableArrayType() const { - return getCaptureKind() == VCK_VLAType; - } - - /// \brief Retrieve the declaration of the variable being captured. - /// - /// This operation is only valid if this capture captures a variable. - VarDecl *getCapturedVar() const; - - friend class ASTStmtReader; - }; - -private: - /// \brief The number of variable captured, including 'this'. - unsigned NumCaptures; - - /// \brief The pointer part is the implicit the outlined function and the - /// int part is the captured region kind, 'CR_Default' etc. - llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind; - - /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl. - RecordDecl *TheRecordDecl; - - /// \brief Construct a captured statement. - CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures, - ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD); - - /// \brief Construct an empty captured statement. - CapturedStmt(EmptyShell Empty, unsigned NumCaptures); - - Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); } - - Stmt *const *getStoredStmts() const { - return reinterpret_cast<Stmt *const *>(this + 1); - } - - Capture *getStoredCaptures() const; - - void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; } - -public: - static CapturedStmt *Create(const ASTContext &Context, Stmt *S, - CapturedRegionKind Kind, - ArrayRef<Capture> Captures, - ArrayRef<Expr *> CaptureInits, - CapturedDecl *CD, RecordDecl *RD); - - static CapturedStmt *CreateDeserialized(const ASTContext &Context, - unsigned NumCaptures); - - /// \brief Retrieve the statement being captured. - Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; } - const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; } - - /// \brief Retrieve the outlined function declaration. - CapturedDecl *getCapturedDecl(); - const CapturedDecl *getCapturedDecl() const; - - /// \brief Set the outlined function declaration. - void setCapturedDecl(CapturedDecl *D); - - /// \brief Retrieve the captured region kind. - CapturedRegionKind getCapturedRegionKind() const; - - /// \brief Set the captured region kind. - void setCapturedRegionKind(CapturedRegionKind Kind); - - /// \brief Retrieve the record declaration for captured variables. - const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; } - - /// \brief Set the record declaration for captured variables. - void setCapturedRecordDecl(RecordDecl *D) { - assert(D && "null RecordDecl"); - TheRecordDecl = D; - } - - /// \brief True if this variable has been captured. - bool capturesVariable(const VarDecl *Var) const; - - /// \brief An iterator that walks over the captures. - typedef Capture *capture_iterator; - typedef const Capture *const_capture_iterator; - typedef llvm::iterator_range<capture_iterator> capture_range; - typedef llvm::iterator_range<const_capture_iterator> capture_const_range; - - capture_range captures() { - return capture_range(capture_begin(), capture_end()); - } - capture_const_range captures() const { - return capture_const_range(capture_begin(), capture_end()); - } - - /// \brief Retrieve an iterator pointing to the first capture. - capture_iterator capture_begin() { return getStoredCaptures(); } - const_capture_iterator capture_begin() const { return getStoredCaptures(); } - - /// \brief Retrieve an iterator pointing past the end of the sequence of - /// captures. - capture_iterator capture_end() const { - return getStoredCaptures() + NumCaptures; - } - - /// \brief Retrieve the number of captures, including 'this'. - unsigned capture_size() const { return NumCaptures; } - - /// \brief Iterator that walks over the capture initialization arguments. - typedef Expr **capture_init_iterator; - typedef llvm::iterator_range<capture_init_iterator> capture_init_range; - - /// \brief Const iterator that walks over the capture initialization - /// arguments. - typedef Expr *const *const_capture_init_iterator; - typedef llvm::iterator_range<const_capture_init_iterator> - const_capture_init_range; - - capture_init_range capture_inits() { - return capture_init_range(capture_init_begin(), capture_init_end()); - } - - const_capture_init_range capture_inits() const { - return const_capture_init_range(capture_init_begin(), capture_init_end()); - } - - /// \brief Retrieve the first initialization argument. - capture_init_iterator capture_init_begin() { - return reinterpret_cast<Expr **>(getStoredStmts()); - } - - const_capture_init_iterator capture_init_begin() const { - return reinterpret_cast<Expr *const *>(getStoredStmts()); - } - - /// \brief Retrieve the iterator pointing one past the last initialization - /// argument. - capture_init_iterator capture_init_end() { - return capture_init_begin() + NumCaptures; - } - - const_capture_init_iterator capture_init_end() const { - return capture_init_begin() + NumCaptures; - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getCapturedStmt()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getCapturedStmt()->getLocEnd(); - } - SourceRange getSourceRange() const LLVM_READONLY { - return getCapturedStmt()->getSourceRange(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CapturedStmtClass; - } - - child_range children(); - - friend class ASTStmtReader; -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h deleted file mode 100644 index 1ca73e2..0000000 --- a/include/clang/AST/StmtCXX.h +++ /dev/null @@ -1,417 +0,0 @@ -//===--- StmtCXX.h - Classes for representing C++ statements ----*- 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 C++ statement AST node classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMTCXX_H -#define LLVM_CLANG_AST_STMTCXX_H - -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/Stmt.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -class VarDecl; - -/// CXXCatchStmt - This represents a C++ catch block. -/// -class CXXCatchStmt : public Stmt { - SourceLocation CatchLoc; - /// The exception-declaration of the type. - VarDecl *ExceptionDecl; - /// The handler block. - Stmt *HandlerBlock; - -public: - CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) - : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), - HandlerBlock(handlerBlock) {} - - CXXCatchStmt(EmptyShell Empty) - : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {} - - SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return HandlerBlock->getLocEnd(); - } - - SourceLocation getCatchLoc() const { return CatchLoc; } - VarDecl *getExceptionDecl() const { return ExceptionDecl; } - QualType getCaughtType() const; - Stmt *getHandlerBlock() const { return HandlerBlock; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXCatchStmtClass; - } - - child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } - - friend class ASTStmtReader; -}; - -/// CXXTryStmt - A C++ try block, including all handlers. -/// -class CXXTryStmt : public Stmt { - SourceLocation TryLoc; - unsigned NumHandlers; - - CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); - - CXXTryStmt(EmptyShell Empty, unsigned numHandlers) - : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } - - Stmt const * const *getStmts() const { - return reinterpret_cast<Stmt const * const*>(this + 1); - } - Stmt **getStmts() { - return reinterpret_cast<Stmt **>(this + 1); - } - -public: - static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, ArrayRef<Stmt*> handlers); - - static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, - unsigned numHandlers); - - SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - SourceLocation getTryLoc() const { return TryLoc; } - SourceLocation getEndLoc() const { - return getStmts()[NumHandlers]->getLocEnd(); - } - - CompoundStmt *getTryBlock() { - return cast<CompoundStmt>(getStmts()[0]); - } - const CompoundStmt *getTryBlock() const { - return cast<CompoundStmt>(getStmts()[0]); - } - - unsigned getNumHandlers() const { return NumHandlers; } - CXXCatchStmt *getHandler(unsigned i) { - return cast<CXXCatchStmt>(getStmts()[i + 1]); - } - const CXXCatchStmt *getHandler(unsigned i) const { - return cast<CXXCatchStmt>(getStmts()[i + 1]); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXTryStmtClass; - } - - child_range children() { - return child_range(getStmts(), getStmts() + getNumHandlers() + 1); - } - - friend class ASTStmtReader; -}; - -/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for -/// statement, represented as 'for (range-declarator : range-expression)'. -/// -/// This is stored in a partially-desugared form to allow full semantic -/// analysis of the constituent components. The original syntactic components -/// can be extracted using getLoopVariable and getRangeInit. -class CXXForRangeStmt : public Stmt { - SourceLocation ForLoc; - enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; - // SubExprs[RANGE] is an expression or declstmt. - // SubExprs[COND] and SubExprs[INC] are expressions. - Stmt *SubExprs[END]; - SourceLocation CoawaitLoc; - SourceLocation ColonLoc; - SourceLocation RParenLoc; - - friend class ASTStmtReader; -public: - CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, - Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, - SourceLocation FL, SourceLocation CAL, SourceLocation CL, - SourceLocation RPL); - CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } - - - VarDecl *getLoopVariable(); - Expr *getRangeInit(); - - const VarDecl *getLoopVariable() const; - const Expr *getRangeInit() const; - - - DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } - DeclStmt *getBeginEndStmt() { - return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); - } - Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } - Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } - DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } - Stmt *getBody() { return SubExprs[BODY]; } - - const DeclStmt *getRangeStmt() const { - return cast<DeclStmt>(SubExprs[RANGE]); - } - const DeclStmt *getBeginEndStmt() const { - return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); - } - const Expr *getCond() const { - return cast_or_null<Expr>(SubExprs[COND]); - } - const Expr *getInc() const { - return cast_or_null<Expr>(SubExprs[INC]); - } - const DeclStmt *getLoopVarStmt() const { - return cast<DeclStmt>(SubExprs[LOOPVAR]); - } - const Stmt *getBody() const { return SubExprs[BODY]; } - - void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } - void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } - void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } - void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } - void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } - void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - - SourceLocation getForLoc() const { return ForLoc; } - SourceLocation getCoawaitLoc() const { return CoawaitLoc; } - SourceLocation getColonLoc() const { return ColonLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXForRangeStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[END]); - } -}; - -/// \brief Representation of a Microsoft __if_exists or __if_not_exists -/// statement with a dependent name. -/// -/// The __if_exists statement can be used to include a sequence of statements -/// in the program only when a particular dependent name does not exist. For -/// example: -/// -/// \code -/// template<typename T> -/// void call_foo(T &t) { -/// __if_exists (T::foo) { -/// t.foo(); // okay: only called when T::foo exists. -/// } -/// } -/// \endcode -/// -/// Similarly, the __if_not_exists statement can be used to include the -/// statements when a particular name does not exist. -/// -/// Note that this statement only captures __if_exists and __if_not_exists -/// statements whose name is dependent. All non-dependent cases are handled -/// directly in the parser, so that they don't introduce a new scope. Clang -/// introduces scopes in the dependent case to keep names inside the compound -/// statement from leaking out into the surround statements, which would -/// compromise the template instantiation model. This behavior differs from -/// Visual C++ (which never introduces a scope), but is a fairly reasonable -/// approximation of the VC++ behavior. -class MSDependentExistsStmt : public Stmt { - SourceLocation KeywordLoc; - bool IsIfExists; - NestedNameSpecifierLoc QualifierLoc; - DeclarationNameInfo NameInfo; - Stmt *SubStmt; - - friend class ASTReader; - friend class ASTStmtReader; - -public: - MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, - NestedNameSpecifierLoc QualifierLoc, - DeclarationNameInfo NameInfo, - CompoundStmt *SubStmt) - : Stmt(MSDependentExistsStmtClass), - KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), - QualifierLoc(QualifierLoc), NameInfo(NameInfo), - SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } - - /// \brief Retrieve the location of the __if_exists or __if_not_exists - /// keyword. - SourceLocation getKeywordLoc() const { return KeywordLoc; } - - /// \brief Determine whether this is an __if_exists statement. - bool isIfExists() const { return IsIfExists; } - - /// \brief Determine whether this is an __if_exists statement. - bool isIfNotExists() const { return !IsIfExists; } - - /// \brief Retrieve the nested-name-specifier that qualifies this name, if - /// any. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// \brief Retrieve the name of the entity we're testing for, along with - /// location information - DeclarationNameInfo getNameInfo() const { return NameInfo; } - - /// \brief Retrieve the compound statement that will be included in the - /// program only if the existence of the symbol matches the initial keyword. - CompoundStmt *getSubStmt() const { - return reinterpret_cast<CompoundStmt *>(SubStmt); - } - - SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} - - child_range children() { - return child_range(&SubStmt, &SubStmt+1); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == MSDependentExistsStmtClass; - } -}; - -/// \brief Represents the body of a coroutine. This wraps the normal function -/// body and holds the additional semantic context required to set up and tear -/// down the coroutine frame. -class CoroutineBodyStmt : public Stmt { - enum SubStmt { - Body, ///< The body of the coroutine. - Promise, ///< The promise statement. - InitSuspend, ///< The initial suspend statement, run before the body. - FinalSuspend, ///< The final suspend statement, run after the body. - OnException, ///< Handler for exceptions thrown in the body. - OnFallthrough, ///< Handler for control flow falling off the body. - ReturnValue, ///< Return value for thunk function. - FirstParamMove ///< First offset for move construction of parameter copies. - }; - Stmt *SubStmts[SubStmt::FirstParamMove]; - - friend class ASTStmtReader; -public: - CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend, - Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough, - Expr *ReturnValue, ArrayRef<Expr *> ParamMoves) - : Stmt(CoroutineBodyStmtClass) { - SubStmts[CoroutineBodyStmt::Body] = Body; - SubStmts[CoroutineBodyStmt::Promise] = Promise; - SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend; - SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend; - SubStmts[CoroutineBodyStmt::OnException] = OnException; - SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough; - SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue; - // FIXME: Tail-allocate space for parameter move expressions and store them. - assert(ParamMoves.empty() && "not implemented yet"); - } - - /// \brief Retrieve the body of the coroutine as written. This will be either - /// a CompoundStmt or a TryStmt. - Stmt *getBody() const { - return SubStmts[SubStmt::Body]; - } - - Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; } - VarDecl *getPromiseDecl() const { - return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); - } - - Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; } - Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; } - - Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; } - Stmt *getFallthroughHandler() const { - return SubStmts[SubStmt::OnFallthrough]; - } - - Expr *getReturnValueInit() const { - return cast<Expr>(SubStmts[SubStmt::ReturnValue]); - } - - SourceLocation getLocStart() const LLVM_READONLY { - return getBody()->getLocStart(); - } - SourceLocation getLocEnd() const LLVM_READONLY { - return getBody()->getLocEnd(); - } - - child_range children() { - return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CoroutineBodyStmtClass; - } -}; - -/// \brief Represents a 'co_return' statement in the C++ Coroutines TS. -/// -/// This statament models the initialization of the coroutine promise -/// (encapsulating the eventual notional return value) from an expression -/// (or braced-init-list), followed by termination of the coroutine. -/// -/// This initialization is modeled by the evaluation of the operand -/// followed by a call to one of: -/// <promise>.return_value(<operand>) -/// <promise>.return_void() -/// which we name the "promise call". -class CoreturnStmt : public Stmt { - SourceLocation CoreturnLoc; - - enum SubStmt { Operand, PromiseCall, Count }; - Stmt *SubStmts[SubStmt::Count]; - - friend class ASTStmtReader; -public: - CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall) - : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) { - SubStmts[SubStmt::Operand] = Operand; - SubStmts[SubStmt::PromiseCall] = PromiseCall; - } - - SourceLocation getKeywordLoc() const { return CoreturnLoc; } - - /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr - /// if none was specified. - Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } - - /// \brief Retrieve the promise call that results from this 'co_return' - /// statement. Will be nullptr if either the coroutine has not yet been - /// finalized or the coroutine has no eventual return type. - Expr *getPromiseCall() const { - return static_cast<Expr*>(SubStmts[PromiseCall]); - } - - SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getOperand()->getLocEnd(); - } - - child_range children() { - return child_range(SubStmts, SubStmts + SubStmt::Count); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CoreturnStmtClass; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h deleted file mode 100644 index ab636a5..0000000 --- a/include/clang/AST/StmtGraphTraits.h +++ /dev/null @@ -1,83 +0,0 @@ -//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- 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 a template specialization of llvm::GraphTraits to -// treat ASTs (Stmt*) as graphs -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMTGRAPHTRAITS_H -#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H - -#include "clang/AST/Stmt.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/GraphTraits.h" - -namespace llvm { - -//template <typename T> struct GraphTraits; - - -template <> struct GraphTraits<clang::Stmt*> { - typedef clang::Stmt NodeType; - typedef clang::Stmt::child_iterator ChildIteratorType; - typedef llvm::df_iterator<clang::Stmt*> nodes_iterator; - - static NodeType* getEntryNode(clang::Stmt* S) { return S; } - - static inline ChildIteratorType child_begin(NodeType* N) { - if (N) return N->child_begin(); - else return ChildIteratorType(); - } - - static inline ChildIteratorType child_end(NodeType* N) { - if (N) return N->child_end(); - else return ChildIteratorType(); - } - - static nodes_iterator nodes_begin(clang::Stmt* S) { - return df_begin(S); - } - - static nodes_iterator nodes_end(clang::Stmt* S) { - return df_end(S); - } -}; - - -template <> struct GraphTraits<const clang::Stmt*> { - typedef const clang::Stmt NodeType; - typedef clang::Stmt::const_child_iterator ChildIteratorType; - typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator; - - static NodeType* getEntryNode(const clang::Stmt* S) { return S; } - - static inline ChildIteratorType child_begin(NodeType* N) { - if (N) return N->child_begin(); - else return ChildIteratorType(); - } - - static inline ChildIteratorType child_end(NodeType* N) { - if (N) return N->child_end(); - else return ChildIteratorType(); - } - - static nodes_iterator nodes_begin(const clang::Stmt* S) { - return df_begin(S); - } - - static nodes_iterator nodes_end(const clang::Stmt* S) { - return df_end(S); - } -}; - - -} // end namespace llvm - -#endif diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h deleted file mode 100644 index 81f8ad43..0000000 --- a/include/clang/AST/StmtIterator.h +++ /dev/null @@ -1,144 +0,0 @@ -//===--- StmtIterator.h - Iterators for Statements --------------*- 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 StmtIterator and ConstStmtIterator classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMTITERATOR_H -#define LLVM_CLANG_AST_STMTITERATOR_H - -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" -#include <cassert> -#include <cstddef> -#include <iterator> -#include <utility> - -namespace clang { - -class Stmt; -class Decl; -class VariableArrayType; - -class StmtIteratorBase { -protected: - enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2, - Flags = 0x3 }; - - union { - Stmt **stmt; - Decl **DGI; - }; - uintptr_t RawVAPtr; - Decl **DGE; - - bool inDeclGroup() const { - return (RawVAPtr & Flags) == DeclGroupMode; - } - - bool inSizeOfTypeVA() const { - return (RawVAPtr & Flags) == SizeOfTypeVAMode; - } - - bool inStmt() const { - return (RawVAPtr & Flags) == StmtMode; - } - - const VariableArrayType *getVAPtr() const { - return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags); - } - - void setVAPtr(const VariableArrayType *P) { - assert (inDeclGroup() || inSizeOfTypeVA()); - RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags); - } - - void NextDecl(bool ImmediateAdvance = true); - bool HandleDecl(Decl* D); - void NextVA(); - - Stmt*& GetDeclExpr() const; - - StmtIteratorBase(Stmt **s) : stmt(s), RawVAPtr(0) {} - StmtIteratorBase(const VariableArrayType *t); - StmtIteratorBase(Decl **dgi, Decl **dge); - StmtIteratorBase() : stmt(nullptr), RawVAPtr(0) {} -}; - - -template <typename DERIVED, typename REFERENCE> -class StmtIteratorImpl : public StmtIteratorBase, - public std::iterator<std::forward_iterator_tag, - REFERENCE, ptrdiff_t, - REFERENCE, REFERENCE> { -protected: - StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} -public: - StmtIteratorImpl() {} - StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} - StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} - StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {} - - DERIVED& operator++() { - if (inStmt()) - ++stmt; - else if (getVAPtr()) - NextVA(); - else - NextDecl(); - - return static_cast<DERIVED&>(*this); - } - - DERIVED operator++(int) { - DERIVED tmp = static_cast<DERIVED&>(*this); - operator++(); - return tmp; - } - - bool operator==(const DERIVED& RHS) const { - return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr; - } - - bool operator!=(const DERIVED& RHS) const { - return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr; - } - - REFERENCE operator*() const { - return inStmt() ? *stmt : GetDeclExpr(); - } - - REFERENCE operator->() const { return operator*(); } -}; - -struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { - explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} - - StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {} - - StmtIterator(Decl** dgi, Decl** dge) - : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} - - StmtIterator(const VariableArrayType *t) - : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} -}; - -struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, - const Stmt*> { - explicit ConstStmtIterator() : - StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {} - - ConstStmtIterator(const StmtIterator& RHS) : - StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h deleted file mode 100644 index 68fe3ef..0000000 --- a/include/clang/AST/StmtObjC.h +++ /dev/null @@ -1,375 +0,0 @@ -//===--- StmtObjC.h - Classes for representing ObjC statements --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -/// \file -/// \brief Defines the Objective-C statement AST node classes. - -#ifndef LLVM_CLANG_AST_STMTOBJC_H -#define LLVM_CLANG_AST_STMTOBJC_H - -#include "clang/AST/Stmt.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - -/// \brief Represents Objective-C's collection statement. -/// -/// This is represented as 'for (element 'in' collection-expression)' stmt. -class ObjCForCollectionStmt : public Stmt { - enum { ELEM, COLLECTION, BODY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt. - SourceLocation ForLoc; - SourceLocation RParenLoc; -public: - ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, - SourceLocation FCL, SourceLocation RPL); - explicit ObjCForCollectionStmt(EmptyShell Empty) : - Stmt(ObjCForCollectionStmtClass, Empty) { } - - Stmt *getElement() { return SubExprs[ELEM]; } - Expr *getCollection() { - return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); - } - Stmt *getBody() { return SubExprs[BODY]; } - - const Stmt *getElement() const { return SubExprs[ELEM]; } - const Expr *getCollection() const { - return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); - } - const Stmt *getBody() const { return SubExprs[BODY]; } - - void setElement(Stmt *S) { SubExprs[ELEM] = S; } - void setCollection(Expr *E) { - SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); - } - void setBody(Stmt *S) { SubExprs[BODY] = S; } - - SourceLocation getForLoc() const { return ForLoc; } - void setForLoc(SourceLocation Loc) { ForLoc = Loc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - - SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCForCollectionStmtClass; - } - - // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[END_EXPR]); - } -}; - -/// \brief Represents Objective-C's \@catch statement. -class ObjCAtCatchStmt : public Stmt { -private: - VarDecl *ExceptionDecl; - Stmt *Body; - SourceLocation AtCatchLoc, RParenLoc; - -public: - ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, - VarDecl *catchVarDecl, - Stmt *atCatchStmt) - : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), - Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } - - explicit ObjCAtCatchStmt(EmptyShell Empty) : - Stmt(ObjCAtCatchStmtClass, Empty) { } - - const Stmt *getCatchBody() const { return Body; } - Stmt *getCatchBody() { return Body; } - void setCatchBody(Stmt *S) { Body = S; } - - const VarDecl *getCatchParamDecl() const { - return ExceptionDecl; - } - VarDecl *getCatchParamDecl() { - return ExceptionDecl; - } - void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } - - SourceLocation getAtCatchLoc() const { return AtCatchLoc; } - void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); } - - bool hasEllipsis() const { return getCatchParamDecl() == nullptr; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAtCatchStmtClass; - } - - child_range children() { return child_range(&Body, &Body + 1); } -}; - -/// \brief Represents Objective-C's \@finally statement -class ObjCAtFinallyStmt : public Stmt { - SourceLocation AtFinallyLoc; - Stmt *AtFinallyStmt; - -public: - ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) - : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc), - AtFinallyStmt(atFinallyStmt) {} - - explicit ObjCAtFinallyStmt(EmptyShell Empty) : - Stmt(ObjCAtFinallyStmtClass, Empty) { } - - const Stmt *getFinallyBody() const { return AtFinallyStmt; } - Stmt *getFinallyBody() { return AtFinallyStmt; } - void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return AtFinallyStmt->getLocEnd(); - } - - SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } - void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAtFinallyStmtClass; - } - - child_range children() { - return child_range(&AtFinallyStmt, &AtFinallyStmt+1); - } -}; - -/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement. -class ObjCAtTryStmt : public Stmt { -private: - // The location of the @ in the \@try. - SourceLocation AtTryLoc; - - // The number of catch blocks in this statement. - unsigned NumCatchStmts : 16; - - // Whether this statement has a \@finally statement. - bool HasFinally : 1; - - /// \brief Retrieve the statements that are stored after this \@try statement. - /// - /// The order of the statements in memory follows the order in the source, - /// with the \@try body first, followed by the \@catch statements (if any) - /// and, finally, the \@finally (if it exists). - Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } - const Stmt* const *getStmts() const { - return reinterpret_cast<const Stmt * const*> (this + 1); - } - - ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt **CatchStmts, unsigned NumCatchStmts, - Stmt *atFinallyStmt); - - explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, - bool HasFinally) - : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), - HasFinally(HasFinally) { } - -public: - static ObjCAtTryStmt *Create(const ASTContext &Context, - SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt **CatchStmts, unsigned NumCatchStmts, - Stmt *atFinallyStmt); - static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context, - unsigned NumCatchStmts, bool HasFinally); - - /// \brief Retrieve the location of the @ in the \@try. - SourceLocation getAtTryLoc() const { return AtTryLoc; } - void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - - /// \brief Retrieve the \@try body. - const Stmt *getTryBody() const { return getStmts()[0]; } - Stmt *getTryBody() { return getStmts()[0]; } - void setTryBody(Stmt *S) { getStmts()[0] = S; } - - /// \brief Retrieve the number of \@catch statements in this try-catch-finally - /// block. - unsigned getNumCatchStmts() const { return NumCatchStmts; } - - /// \brief Retrieve a \@catch statement. - const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { - assert(I < NumCatchStmts && "Out-of-bounds @catch index"); - return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); - } - - /// \brief Retrieve a \@catch statement. - ObjCAtCatchStmt *getCatchStmt(unsigned I) { - assert(I < NumCatchStmts && "Out-of-bounds @catch index"); - return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); - } - - /// \brief Set a particular catch statement. - void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { - assert(I < NumCatchStmts && "Out-of-bounds @catch index"); - getStmts()[I + 1] = S; - } - - /// \brief Retrieve the \@finally statement, if any. - const ObjCAtFinallyStmt *getFinallyStmt() const { - if (!HasFinally) - return nullptr; - - return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); - } - ObjCAtFinallyStmt *getFinallyStmt() { - if (!HasFinally) - return nullptr; - - return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); - } - void setFinallyStmt(Stmt *S) { - assert(HasFinally && "@try does not have a @finally slot!"); - getStmts()[1 + NumCatchStmts] = S; - } - - SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; } - SourceLocation getLocEnd() const LLVM_READONLY; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAtTryStmtClass; - } - - child_range children() { - return child_range(getStmts(), - getStmts() + 1 + NumCatchStmts + HasFinally); - } -}; - -/// \brief Represents Objective-C's \@synchronized statement. -/// -/// Example: -/// \code -/// @synchronized (sem) { -/// do-something; -/// } -/// \endcode -class ObjCAtSynchronizedStmt : public Stmt { -private: - SourceLocation AtSynchronizedLoc; - enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; - Stmt* SubStmts[END_EXPR]; - -public: - ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, - Stmt *synchBody) - : Stmt(ObjCAtSynchronizedStmtClass) { - SubStmts[SYNC_EXPR] = synchExpr; - SubStmts[SYNC_BODY] = synchBody; - AtSynchronizedLoc = atSynchronizedLoc; - } - explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : - Stmt(ObjCAtSynchronizedStmtClass, Empty) { } - - SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } - void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } - - const CompoundStmt *getSynchBody() const { - return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); - } - CompoundStmt *getSynchBody() { - return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); - } - void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } - - const Expr *getSynchExpr() const { - return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); - } - Expr *getSynchExpr() { - return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); - } - void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getSynchBody()->getLocEnd(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAtSynchronizedStmtClass; - } - - child_range children() { - return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR); - } -}; - -/// \brief Represents Objective-C's \@throw statement. -class ObjCAtThrowStmt : public Stmt { - SourceLocation AtThrowLoc; - Stmt *Throw; - -public: - ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) - : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { - AtThrowLoc = atThrowLoc; - } - explicit ObjCAtThrowStmt(EmptyShell Empty) : - Stmt(ObjCAtThrowStmtClass, Empty) { } - - const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } - Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } - void setThrowExpr(Stmt *S) { Throw = S; } - - SourceLocation getThrowLoc() { return AtThrowLoc; } - void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return Throw ? Throw->getLocEnd() : AtThrowLoc; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAtThrowStmtClass; - } - - child_range children() { return child_range(&Throw, &Throw+1); } -}; - -/// \brief Represents Objective-C's \@autoreleasepool Statement -class ObjCAutoreleasePoolStmt : public Stmt { - SourceLocation AtLoc; - Stmt *SubStmt; - -public: - ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt) - : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {} - - explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) : - Stmt(ObjCAutoreleasePoolStmtClass, Empty) { } - - const Stmt *getSubStmt() const { return SubStmt; } - Stmt *getSubStmt() { return SubStmt; } - void setSubStmt(Stmt *S) { SubStmt = S; } - - SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} - - SourceLocation getAtLoc() const { return AtLoc; } - void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; - } - - child_range children() { return child_range(&SubStmt, &SubStmt + 1); } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h deleted file mode 100644 index 1ba859c..0000000 --- a/include/clang/AST/StmtOpenMP.h +++ /dev/null @@ -1,2422 +0,0 @@ -//===- StmtOpenMP.h - Classes for OpenMP directives ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// \brief This file defines OpenMP AST classes for executable directives and -/// clauses. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMTOPENMP_H -#define LLVM_CLANG_AST_STMTOPENMP_H - -#include "clang/AST/Expr.h" -#include "clang/AST/OpenMPClause.h" -#include "clang/AST/Stmt.h" -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/SourceLocation.h" - -namespace clang { - -//===----------------------------------------------------------------------===// -// AST classes for directives. -//===----------------------------------------------------------------------===// - -/// \brief This is a basic class for representing single OpenMP executable -/// directive. -/// -class OMPExecutableDirective : public Stmt { - friend class ASTStmtReader; - /// \brief Kind of the directive. - OpenMPDirectiveKind Kind; - /// \brief Starting location of the directive (directive keyword). - SourceLocation StartLoc; - /// \brief Ending location of the directive. - SourceLocation EndLoc; - /// \brief Numbers of clauses. - const unsigned NumClauses; - /// \brief Number of child expressions/stmts. - const unsigned NumChildren; - /// \brief Offset from this to the start of clauses. - /// There are NumClauses pointers to clauses, they are followed by - /// NumChildren pointers to child stmts/exprs (if the directive type - /// requires an associated stmt, then it has to be the first of them). - const unsigned ClausesOffset; - - /// \brief Get the clauses storage. - MutableArrayRef<OMPClause *> getClauses() { - OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>( - reinterpret_cast<char *>(this) + ClausesOffset); - return MutableArrayRef<OMPClause *>(ClauseStorage, NumClauses); - } - -protected: - /// \brief Build instance of directive of class \a K. - /// - /// \param SC Statement class. - /// \param K Kind of OpenMP directive. - /// \param StartLoc Starting location of the directive (directive keyword). - /// \param EndLoc Ending location of the directive. - /// - template <typename T> - OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K, - SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses, unsigned NumChildren) - : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)), - EndLoc(std::move(EndLoc)), NumClauses(NumClauses), - NumChildren(NumChildren), - ClausesOffset(llvm::RoundUpToAlignment(sizeof(T), - llvm::alignOf<OMPClause *>())) {} - - /// \brief Sets the list of variables for this clause. - /// - /// \param Clauses The list of clauses for the directive. - /// - void setClauses(ArrayRef<OMPClause *> Clauses); - - /// \brief Set the associated statement for the directive. - /// - /// /param S Associated statement. - /// - void setAssociatedStmt(Stmt *S) { - assert(hasAssociatedStmt() && "no associated statement."); - *child_begin() = S; - } - -public: - /// \brief Iterates over a filtered subrange of clauses applied to a - /// directive. - /// - /// This iterator visits only clauses of type SpecificClause. - template <typename SpecificClause> - class specific_clause_iterator - : public llvm::iterator_adaptor_base< - specific_clause_iterator<SpecificClause>, - ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag, - const SpecificClause *, ptrdiff_t, const SpecificClause *, - const SpecificClause *> { - ArrayRef<OMPClause *>::const_iterator End; - - void SkipToNextClause() { - while (this->I != End && !isa<SpecificClause>(*this->I)) - ++this->I; - } - - public: - explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses) - : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()), - End(Clauses.end()) { - SkipToNextClause(); - } - - const SpecificClause *operator*() const { - return cast<SpecificClause>(*this->I); - } - const SpecificClause *operator->() const { return **this; } - - specific_clause_iterator &operator++() { - ++this->I; - SkipToNextClause(); - return *this; - } - }; - - template <typename SpecificClause> - static llvm::iterator_range<specific_clause_iterator<SpecificClause>> - getClausesOfKind(ArrayRef<OMPClause *> Clauses) { - return {specific_clause_iterator<SpecificClause>(Clauses), - specific_clause_iterator<SpecificClause>( - llvm::makeArrayRef(Clauses.end(), 0))}; - } - - template <typename SpecificClause> - llvm::iterator_range<specific_clause_iterator<SpecificClause>> - getClausesOfKind() const { - return getClausesOfKind<SpecificClause>(clauses()); - } - - /// Gets a single clause of the specified kind associated with the - /// current directive iff there is only one clause of this kind (and assertion - /// is fired if there is more than one clause is associated with the - /// directive). Returns nullptr if no clause of this kind is associated with - /// the directive. - template <typename SpecificClause> - const SpecificClause *getSingleClause() const { - auto Clauses = getClausesOfKind<SpecificClause>(); - - if (Clauses.begin() != Clauses.end()) { - assert(std::next(Clauses.begin()) == Clauses.end() && - "There are at least 2 clauses of the specified kind"); - return *Clauses.begin(); - } - return nullptr; - } - - /// Returns true if the current directive has one or more clauses of a - /// specific kind. - template <typename SpecificClause> - bool hasClausesOfKind() const { - auto Clauses = getClausesOfKind<SpecificClause>(); - return Clauses.begin() != Clauses.end(); - } - - /// \brief Returns starting location of directive kind. - SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns ending location of directive. - SourceLocation getLocEnd() const { return EndLoc; } - - /// \brief Set starting location of directive kind. - /// - /// \param Loc New starting location of directive. - /// - void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Set ending location of directive. - /// - /// \param Loc New ending location of directive. - /// - void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } - - /// \brief Get number of clauses. - unsigned getNumClauses() const { return NumClauses; } - - /// \brief Returns specified clause. - /// - /// \param i Number of clause. - /// - OMPClause *getClause(unsigned i) const { return clauses()[i]; } - - /// \brief Returns true if directive has associated statement. - bool hasAssociatedStmt() const { return NumChildren > 0; } - - /// \brief Returns statement associated with the directive. - Stmt *getAssociatedStmt() const { - assert(hasAssociatedStmt() && "no associated statement."); - return const_cast<Stmt *>(*child_begin()); - } - - OpenMPDirectiveKind getDirectiveKind() const { return Kind; } - - static bool classof(const Stmt *S) { - return S->getStmtClass() >= firstOMPExecutableDirectiveConstant && - S->getStmtClass() <= lastOMPExecutableDirectiveConstant; - } - - child_range children() { - if (!hasAssociatedStmt()) - return child_range(child_iterator(), child_iterator()); - Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end()); - return child_range(ChildStorage, ChildStorage + NumChildren); - } - - ArrayRef<OMPClause *> clauses() { return getClauses(); } - - ArrayRef<OMPClause *> clauses() const { - return const_cast<OMPExecutableDirective *>(this)->getClauses(); - } -}; - -/// \brief This represents '#pragma omp parallel' directive. -/// -/// \code -/// #pragma omp parallel private(a,b) reduction(+: c,d) -/// \endcode -/// In this example directive '#pragma omp parallel' has clauses 'private' -/// with the variables 'a' and 'b' and 'reduction' with operator '+' and -/// variables 'c' and 'd'. -/// -class OMPParallelDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief true if the construct has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive (directive keyword). - /// \param EndLoc Ending Location of the directive. - /// - OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, - StartLoc, EndLoc, NumClauses, 1), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPParallelDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, - SourceLocation(), SourceLocation(), NumClauses, - 1), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement associated with the directive. - /// \param HasCancel true if this directive has inner cancel directive. - /// - static OMPParallelDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - - /// \brief Creates an empty directive with the place for \a N clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPParallelDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPParallelDirectiveClass; - } -}; - -/// \brief This is a common base class for loop directives ('omp simd', 'omp -/// for', 'omp for simd' etc.). It is responsible for the loop code generation. -/// -class OMPLoopDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; - - /// \brief Offsets to the stored exprs. - /// This enumeration contains offsets to all the pointers to children - /// expressions stored in OMPLoopDirective. - /// The first 9 children are nesessary for all the loop directives, and - /// the next 7 are specific to the worksharing ones. - /// After the fixed children, three arrays of length CollapsedNum are - /// allocated: loop counters, their updates and final values. - /// - enum { - AssociatedStmtOffset = 0, - IterationVariableOffset = 1, - LastIterationOffset = 2, - CalcLastIterationOffset = 3, - PreConditionOffset = 4, - CondOffset = 5, - InitOffset = 6, - IncOffset = 7, - // The '...End' enumerators do not correspond to child expressions - they - // specify the offset to the end (and start of the following counters/ - // updates/finals arrays). - DefaultEnd = 8, - // The following 7 exprs are used by worksharing loops only. - IsLastIterVariableOffset = 8, - LowerBoundVariableOffset = 9, - UpperBoundVariableOffset = 10, - StrideVariableOffset = 11, - EnsureUpperBoundOffset = 12, - NextLowerBoundOffset = 13, - NextUpperBoundOffset = 14, - // Offset to the end (and start of the following counters/updates/finals - // arrays) for worksharing loop directives. - WorksharingEnd = 15, - }; - - /// \brief Get the counters storage. - MutableArrayRef<Expr *> getCounters() { - Expr **Storage = reinterpret_cast<Expr **>( - &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind()))))); - return MutableArrayRef<Expr *>(Storage, CollapsedNum); - } - - /// \brief Get the private counters storage. - MutableArrayRef<Expr *> getPrivateCounters() { - Expr **Storage = reinterpret_cast<Expr **>(&*std::next( - child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum)); - return MutableArrayRef<Expr *>(Storage, CollapsedNum); - } - - /// \brief Get the updates storage. - MutableArrayRef<Expr *> getInits() { - Expr **Storage = reinterpret_cast<Expr **>( - &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); - return MutableArrayRef<Expr *>(Storage, CollapsedNum); - } - - /// \brief Get the updates storage. - MutableArrayRef<Expr *> getUpdates() { - Expr **Storage = reinterpret_cast<Expr **>( - &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum)); - return MutableArrayRef<Expr *>(Storage, CollapsedNum); - } - - /// \brief Get the final counter updates storage. - MutableArrayRef<Expr *> getFinals() { - Expr **Storage = reinterpret_cast<Expr **>( - &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum)); - return MutableArrayRef<Expr *>(Storage, CollapsedNum); - } - -protected: - /// \brief Build instance of loop directive of class \a Kind. - /// - /// \param SC Statement class. - /// \param Kind Kind of OpenMP directive. - /// \param StartLoc Starting location of the directive (directive keyword). - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed loops from 'collapse' clause. - /// \param NumClauses Number of clauses. - /// \param NumSpecialChildren Number of additional directive-specific stmts. - /// - template <typename T> - OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind, - SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses, - unsigned NumSpecialChildren = 0) - : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses, - numLoopChildren(CollapsedNum, Kind) + - NumSpecialChildren), - CollapsedNum(CollapsedNum) {} - - /// \brief Offset to the start of children expression arrays. - static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { - return (isOpenMPWorksharingDirective(Kind) || - isOpenMPTaskLoopDirective(Kind) || - isOpenMPDistributeDirective(Kind)) - ? WorksharingEnd - : DefaultEnd; - } - - /// \brief Children number. - static unsigned numLoopChildren(unsigned CollapsedNum, - OpenMPDirectiveKind Kind) { - return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters, - // PrivateCounters, Inits, - // Updates and Finals - } - - void setIterationVariable(Expr *IV) { - *std::next(child_begin(), IterationVariableOffset) = IV; - } - void setLastIteration(Expr *LI) { - *std::next(child_begin(), LastIterationOffset) = LI; - } - void setCalcLastIteration(Expr *CLI) { - *std::next(child_begin(), CalcLastIterationOffset) = CLI; - } - void setPreCond(Expr *PC) { - *std::next(child_begin(), PreConditionOffset) = PC; - } - void setCond(Expr *Cond) { - *std::next(child_begin(), CondOffset) = Cond; - } - void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } - void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } - void setIsLastIterVariable(Expr *IL) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), IsLastIterVariableOffset) = IL; - } - void setLowerBoundVariable(Expr *LB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), LowerBoundVariableOffset) = LB; - } - void setUpperBoundVariable(Expr *UB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), UpperBoundVariableOffset) = UB; - } - void setStrideVariable(Expr *ST) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), StrideVariableOffset) = ST; - } - void setEnsureUpperBound(Expr *EUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), EnsureUpperBoundOffset) = EUB; - } - void setNextLowerBound(Expr *NLB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), NextLowerBoundOffset) = NLB; - } - void setNextUpperBound(Expr *NUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - *std::next(child_begin(), NextUpperBoundOffset) = NUB; - } - void setCounters(ArrayRef<Expr *> A); - void setPrivateCounters(ArrayRef<Expr *> A); - void setInits(ArrayRef<Expr *> A); - void setUpdates(ArrayRef<Expr *> A); - void setFinals(ArrayRef<Expr *> A); - -public: - /// \brief The expressions built for the OpenMP loop CodeGen for the - /// whole collapsed loop nest. - struct HelperExprs { - /// \brief Loop iteration variable. - Expr *IterationVarRef; - /// \brief Loop last iteration number. - Expr *LastIteration; - /// \brief Loop number of iterations. - Expr *NumIterations; - /// \brief Calculation of last iteration. - Expr *CalcLastIteration; - /// \brief Loop pre-condition. - Expr *PreCond; - /// \brief Loop condition. - Expr *Cond; - /// \brief Loop iteration variable init. - Expr *Init; - /// \brief Loop increment. - Expr *Inc; - /// \brief IsLastIteration - local flag variable passed to runtime. - Expr *IL; - /// \brief LowerBound - local variable passed to runtime. - Expr *LB; - /// \brief UpperBound - local variable passed to runtime. - Expr *UB; - /// \brief Stride - local variable passed to runtime. - Expr *ST; - /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations). - Expr *EUB; - /// \brief Update of LowerBound for statically sheduled 'omp for' loops. - Expr *NLB; - /// \brief Update of UpperBound for statically sheduled 'omp for' loops. - Expr *NUB; - /// \brief Counters Loop counters. - SmallVector<Expr *, 4> Counters; - /// \brief PrivateCounters Loop counters. - SmallVector<Expr *, 4> PrivateCounters; - /// \brief Expressions for loop counters inits for CodeGen. - SmallVector<Expr *, 4> Inits; - /// \brief Expressions for loop counters update for CodeGen. - SmallVector<Expr *, 4> Updates; - /// \brief Final loop counter values for GodeGen. - SmallVector<Expr *, 4> Finals; - - /// \brief Check if all the expressions are built (does not check the - /// worksharing ones). - bool builtAll() { - return IterationVarRef != nullptr && LastIteration != nullptr && - NumIterations != nullptr && PreCond != nullptr && - Cond != nullptr && Init != nullptr && Inc != nullptr; - } - - /// \brief Initialize all the fields to null. - /// \param Size Number of elements in the counters/finals/updates arrays. - void clear(unsigned Size) { - IterationVarRef = nullptr; - LastIteration = nullptr; - CalcLastIteration = nullptr; - PreCond = nullptr; - Cond = nullptr; - Init = nullptr; - Inc = nullptr; - IL = nullptr; - LB = nullptr; - UB = nullptr; - ST = nullptr; - EUB = nullptr; - NLB = nullptr; - NUB = nullptr; - Counters.resize(Size); - PrivateCounters.resize(Size); - Inits.resize(Size); - Updates.resize(Size); - Finals.resize(Size); - for (unsigned i = 0; i < Size; ++i) { - Counters[i] = nullptr; - PrivateCounters[i] = nullptr; - Inits[i] = nullptr; - Updates[i] = nullptr; - Finals[i] = nullptr; - } - } - }; - - /// \brief Get number of collapsed loops. - unsigned getCollapsedNumber() const { return CollapsedNum; } - - Expr *getIterationVariable() const { - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), IterationVariableOffset))); - } - Expr *getLastIteration() const { - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), LastIterationOffset))); - } - Expr *getCalcLastIteration() const { - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), CalcLastIterationOffset))); - } - Expr *getPreCond() const { - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), PreConditionOffset))); - } - Expr *getCond() const { - return const_cast<Expr *>( - reinterpret_cast<const Expr *>(*std::next(child_begin(), CondOffset))); - } - Expr *getInit() const { - return const_cast<Expr *>( - reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset))); - } - Expr *getInc() const { - return const_cast<Expr *>( - reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset))); - } - Expr *getIsLastIterVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), IsLastIterVariableOffset))); - } - Expr *getLowerBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), LowerBoundVariableOffset))); - } - Expr *getUpperBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), UpperBoundVariableOffset))); - } - Expr *getStrideVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), StrideVariableOffset))); - } - Expr *getEnsureUpperBound() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), EnsureUpperBoundOffset))); - } - Expr *getNextLowerBound() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), NextLowerBoundOffset))); - } - Expr *getNextUpperBound() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && - "expected worksharing loop directive"); - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), NextUpperBoundOffset))); - } - const Stmt *getBody() const { - // This relies on the loop form is already checked by Sema. - Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); - Body = cast<ForStmt>(Body)->getBody(); - for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { - Body = Body->IgnoreContainers(); - Body = cast<ForStmt>(Body)->getBody(); - } - return Body; - } - - ArrayRef<Expr *> counters() { return getCounters(); } - - ArrayRef<Expr *> counters() const { - return const_cast<OMPLoopDirective *>(this)->getCounters(); - } - - ArrayRef<Expr *> private_counters() { return getPrivateCounters(); } - - ArrayRef<Expr *> private_counters() const { - return const_cast<OMPLoopDirective *>(this)->getPrivateCounters(); - } - - ArrayRef<Expr *> inits() { return getInits(); } - - ArrayRef<Expr *> inits() const { - return const_cast<OMPLoopDirective *>(this)->getInits(); - } - - ArrayRef<Expr *> updates() { return getUpdates(); } - - ArrayRef<Expr *> updates() const { - return const_cast<OMPLoopDirective *>(this)->getUpdates(); - } - - ArrayRef<Expr *> finals() { return getFinals(); } - - ArrayRef<Expr *> finals() const { - return const_cast<OMPLoopDirective *>(this)->getFinals(); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPSimdDirectiveClass || - T->getStmtClass() == OMPForDirectiveClass || - T->getStmtClass() == OMPForSimdDirectiveClass || - T->getStmtClass() == OMPParallelForDirectiveClass || - T->getStmtClass() == OMPParallelForSimdDirectiveClass || - T->getStmtClass() == OMPTaskLoopDirectiveClass || - T->getStmtClass() == OMPTaskLoopSimdDirectiveClass || - T->getStmtClass() == OMPDistributeDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp simd' directive. -/// -/// \code -/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp simd' has clauses 'private' -/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and -/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. -/// -class OMPSimdDirective : public OMPLoopDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, - EndLoc, CollapsedNum, NumClauses) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, - SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, - const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, - unsigned CollapsedNum, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPSimdDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp for' directive. -/// -/// \code -/// #pragma omp for private(a,b) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp for' has clauses 'private' with the -/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c' -/// and 'd'. -/// -class OMPForDirective : public OMPLoopDirective { - friend class ASTStmtReader; - - /// \brief true if current directive has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc, - CollapsedNum, NumClauses), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// \param HasCancel true if current directive has inner cancel directive. - /// - static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, - bool HasCancel); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, - unsigned CollapsedNum, EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPForDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp for simd' directive. -/// -/// \code -/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp for simd' has clauses 'private' -/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and -/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. -/// -class OMPForSimdDirective : public OMPLoopDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, - StartLoc, EndLoc, CollapsedNum, NumClauses) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, - SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPForSimdDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPForSimdDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPForSimdDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp sections' directive. -/// -/// \code -/// #pragma omp sections private(a,b) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp sections' has clauses 'private' with -/// the variables 'a' and 'b' and 'reduction' with operator '+' and variables -/// 'c' and 'd'. -/// -class OMPSectionsDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - - /// \brief true if current directive has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, - StartLoc, EndLoc, NumClauses, 1), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPSectionsDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, - SourceLocation(), SourceLocation(), NumClauses, - 1), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param HasCancel true if current directive has inner directive. - /// - static OMPSectionsDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPSectionsDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPSectionsDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp section' directive. -/// -/// \code -/// #pragma omp section -/// \endcode -/// -class OMPSectionDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - - /// \brief true if current directive has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, - StartLoc, EndLoc, 0, 1), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - explicit OMPSectionDirective() - : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, - SourceLocation(), SourceLocation(), 0, 1), - HasCancel(false) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param HasCancel true if current directive has inner directive. - /// - static OMPSectionDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt, bool HasCancel); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPSectionDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp single' directive. -/// -/// \code -/// #pragma omp single private(a,b) copyprivate(c,d) -/// \endcode -/// In this example directive '#pragma omp single' has clauses 'private' with -/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'. -/// -class OMPSingleDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single, - StartLoc, EndLoc, NumClauses, 1) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPSingleDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single, - SourceLocation(), SourceLocation(), NumClauses, - 1) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPSingleDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPSingleDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPSingleDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp master' directive. -/// -/// \code -/// #pragma omp master -/// \endcode -/// -class OMPMasterDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, - StartLoc, EndLoc, 0, 1) {} - - /// \brief Build an empty directive. - /// - explicit OMPMasterDirective() - : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, - SourceLocation(), SourceLocation(), 0, 1) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPMasterDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPMasterDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp critical' directive. -/// -/// \code -/// #pragma omp critical -/// \endcode -/// -class OMPCriticalDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Name of the directive. - DeclarationNameInfo DirName; - /// \brief Build directive with the given start and end location. - /// - /// \param Name Name of the directive. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned NumClauses) - : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, - StartLoc, EndLoc, NumClauses, 1), - DirName(Name) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPCriticalDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, - SourceLocation(), SourceLocation(), NumClauses, - 1), - DirName() {} - - /// \brief Set name of the directive. - /// - /// \param Name Name of the directive. - /// - void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; } - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param Name Name of the directive. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPCriticalDirective * - Create(const ASTContext &C, const DeclarationNameInfo &Name, - SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPCriticalDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - /// \brief Return name of the directive. - /// - DeclarationNameInfo getDirectiveName() const { return DirName; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPCriticalDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp parallel for' directive. -/// -/// \code -/// #pragma omp parallel for private(a,b) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp parallel for' has clauses 'private' -/// with the variables 'a' and 'b' and 'reduction' with operator '+' and -/// variables 'c' and 'd'. -/// -class OMPParallelForDirective : public OMPLoopDirective { - friend class ASTStmtReader; - - /// \brief true if current region has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, - StartLoc, EndLoc, CollapsedNum, NumClauses), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, - SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// \param HasCancel true if current directive has inner cancel directive. - /// - static OMPParallelForDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPParallelForDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, - EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPParallelForDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp parallel for simd' directive. -/// -/// \code -/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp parallel for simd' has clauses -/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j' -/// and linear step 's', 'reduction' with operator '+' and variables 'c' and -/// 'd'. -/// -class OMPParallelForSimdDirective : public OMPLoopDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, - OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum, - NumClauses) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPParallelForSimdDirective(unsigned CollapsedNum, - unsigned NumClauses) - : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, - OMPD_parallel_for_simd, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPParallelForSimdDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, - EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPParallelForSimdDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp parallel sections' directive. -/// -/// \code -/// #pragma omp parallel sections private(a,b) reduction(+:c,d) -/// \endcode -/// In this example directive '#pragma omp parallel sections' has clauses -/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+' -/// and variables 'c' and 'd'. -/// -class OMPParallelSectionsDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - - /// \brief true if current directive has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, - OMPD_parallel_sections, StartLoc, EndLoc, - NumClauses, 1), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPParallelSectionsDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, - OMPD_parallel_sections, SourceLocation(), - SourceLocation(), NumClauses, 1), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param HasCancel true if current directive has inner cancel directive. - /// - static OMPParallelSectionsDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPParallelSectionsDirective * - CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPParallelSectionsDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp task' directive. -/// -/// \code -/// #pragma omp task private(a,b) final(d) -/// \endcode -/// In this example directive '#pragma omp task' has clauses 'private' with the -/// variables 'a' and 'b' and 'final' with condition 'd'. -/// -class OMPTaskDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief true if this directive has inner cancel directive. - bool HasCancel; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc, - EndLoc, NumClauses, 1), - HasCancel(false) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPTaskDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, - SourceLocation(), SourceLocation(), NumClauses, - 1), - HasCancel(false) {} - - /// \brief Set cancel state. - void setHasCancel(bool Has) { HasCancel = Has; } - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param HasCancel true, if current directive has inner cancel directive. - /// - static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, bool HasCancel); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, - EmptyShell); - - /// \brief Return true if current directive has inner cancel directive. - bool hasCancel() const { return HasCancel; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp taskyield' directive. -/// -/// \code -/// #pragma omp taskyield -/// \endcode -/// -class OMPTaskyieldDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, - StartLoc, EndLoc, 0, 0) {} - - /// \brief Build an empty directive. - /// - explicit OMPTaskyieldDirective() - : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, - SourceLocation(), SourceLocation(), 0, 0) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// - static OMPTaskyieldDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskyieldDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp barrier' directive. -/// -/// \code -/// #pragma omp barrier -/// \endcode -/// -class OMPBarrierDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, - StartLoc, EndLoc, 0, 0) {} - - /// \brief Build an empty directive. - /// - explicit OMPBarrierDirective() - : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, - SourceLocation(), SourceLocation(), 0, 0) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// - static OMPBarrierDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPBarrierDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp taskwait' directive. -/// -/// \code -/// #pragma omp taskwait -/// \endcode -/// -class OMPTaskwaitDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, - StartLoc, EndLoc, 0, 0) {} - - /// \brief Build an empty directive. - /// - explicit OMPTaskwaitDirective() - : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, - SourceLocation(), SourceLocation(), 0, 0) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// - static OMPTaskwaitDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskwaitDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp taskgroup' directive. -/// -/// \code -/// #pragma omp taskgroup -/// \endcode -/// -class OMPTaskgroupDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, - StartLoc, EndLoc, 0, 1) {} - - /// \brief Build an empty directive. - /// - explicit OMPTaskgroupDirective() - : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, - SourceLocation(), SourceLocation(), 0, 1) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPTaskgroupDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskgroupDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp flush' directive. -/// -/// \code -/// #pragma omp flush(a,b) -/// \endcode -/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a' -/// and 'b'. -/// 'omp flush' directive does not have clauses but have an optional list of -/// variables to flush. This list of variables is stored within some fake clause -/// FlushClause. -class OMPFlushDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, - StartLoc, EndLoc, NumClauses, 0) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPFlushDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, - SourceLocation(), SourceLocation(), NumClauses, - 0) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses (only single OMPFlushClause clause is - /// allowed). - /// - static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPFlushDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPFlushDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp ordered' directive. -/// -/// \code -/// #pragma omp ordered -/// \endcode -/// -class OMPOrderedDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, - StartLoc, EndLoc, NumClauses, 1) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPOrderedDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, - SourceLocation(), SourceLocation(), NumClauses, - 1) {} - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPOrderedDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPOrderedDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPOrderedDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp atomic' directive. -/// -/// \code -/// #pragma omp atomic capture -/// \endcode -/// In this example directive '#pragma omp atomic' has clause 'capture'. -/// -class OMPAtomicDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may - /// have atomic expressions of forms - /// \code - /// x = x binop expr; - /// x = expr binop x; - /// \endcode - /// This field is true for the first form of the expression and false for the - /// second. Required for correct codegen of non-associative operations (like - /// << or >>). - bool IsXLHSInRHSPart; - /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may - /// have atomic expressions of forms - /// \code - /// v = x; <update x>; - /// <update x>; v = x; - /// \endcode - /// This field is true for the first(postfix) form of the expression and false - /// otherwise. - bool IsPostfixUpdate; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, - StartLoc, EndLoc, NumClauses, 5), - IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPAtomicDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, - SourceLocation(), SourceLocation(), NumClauses, - 5), - IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} - - /// \brief Set 'x' part of the associated expression/statement. - void setX(Expr *X) { *std::next(child_begin()) = X; } - /// \brief Set helper expression of the form - /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or - /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; } - /// \brief Set 'v' part of the associated expression/statement. - void setV(Expr *V) { *std::next(child_begin(), 3) = V; } - /// \brief Set 'expr' part of the associated expression/statement. - void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; } - -public: - /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' - /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for - /// detailed description of 'x', 'v' and 'expr'). - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param X 'x' part of the associated expression/statement. - /// \param V 'v' part of the associated expression/statement. - /// \param E 'expr' part of the associated expression/statement. - /// \param UE Helper expression of the form - /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or - /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - /// \param IsXLHSInRHSPart true if \a UE has the first form and false if the - /// second. - /// \param IsPostfixUpdate true if original value of 'x' must be stored in - /// 'v', not an updated one. - static OMPAtomicDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPAtomicDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - /// \brief Get 'x' part of the associated expression/statement. - Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); } - const Expr *getX() const { - return cast_or_null<Expr>(*std::next(child_begin())); - } - /// \brief Get helper expression of the form - /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or - /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - Expr *getUpdateExpr() { - return cast_or_null<Expr>(*std::next(child_begin(), 2)); - } - const Expr *getUpdateExpr() const { - return cast_or_null<Expr>(*std::next(child_begin(), 2)); - } - /// \brief Return true if helper update expression has form - /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form - /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } - /// \brief Return true if 'v' expression must be updated to original value of - /// 'x', false if 'v' must be updated to the new value of 'x'. - bool isPostfixUpdate() const { return IsPostfixUpdate; } - /// \brief Get 'v' part of the associated expression/statement. - Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } - const Expr *getV() const { - return cast_or_null<Expr>(*std::next(child_begin(), 3)); - } - /// \brief Get 'expr' part of the associated expression/statement. - Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); } - const Expr *getExpr() const { - return cast_or_null<Expr>(*std::next(child_begin(), 4)); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPAtomicDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp target' directive. -/// -/// \code -/// #pragma omp target if(a) -/// \endcode -/// In this example directive '#pragma omp target' has clause 'if' with -/// condition 'a'. -/// -class OMPTargetDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, - StartLoc, EndLoc, NumClauses, 1) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPTargetDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, - SourceLocation(), SourceLocation(), NumClauses, - 1) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPTargetDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPTargetDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTargetDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp target data' directive. -/// -/// \code -/// #pragma omp target data device(0) if(a) map(b[:]) -/// \endcode -/// In this example directive '#pragma omp target data' has clauses 'device' -/// with the value '0', 'if' with condition 'a' and 'map' with array -/// section 'b[:]'. -/// -class OMPTargetDataDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param NumClauses The number of clauses. - /// - OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPTargetDataDirectiveClass, - OMPD_target_data, StartLoc, EndLoc, NumClauses, - 1) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPTargetDataDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPTargetDataDirectiveClass, - OMPD_target_data, SourceLocation(), - SourceLocation(), NumClauses, 1) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPTargetDataDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - - /// \brief Creates an empty directive with the place for \a N clauses. - /// - /// \param C AST context. - /// \param N The number of clauses. - /// - static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N, - EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTargetDataDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp teams' directive. -/// -/// \code -/// #pragma omp teams if(a) -/// \endcode -/// In this example directive '#pragma omp teams' has clause 'if' with -/// condition 'a'. -/// -class OMPTeamsDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, - StartLoc, EndLoc, NumClauses, 1) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - /// - explicit OMPTeamsDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, - SourceLocation(), SourceLocation(), NumClauses, - 1) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); - - /// \brief Creates an empty directive with the place for \a NumClauses - /// clauses. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPTeamsDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTeamsDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp cancellation point' directive. -/// -/// \code -/// #pragma omp cancellation point for -/// \endcode -/// -/// In this example a cancellation point is created for innermost 'for' region. -class OMPCancellationPointDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - OpenMPDirectiveKind CancelRegion; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// - OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass, - OMPD_cancellation_point, StartLoc, EndLoc, 0, 0), - CancelRegion(OMPD_unknown) {} - - /// \brief Build an empty directive. - /// - explicit OMPCancellationPointDirective() - : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass, - OMPD_cancellation_point, SourceLocation(), - SourceLocation(), 0, 0), - CancelRegion(OMPD_unknown) {} - - /// \brief Set cancel region for current cancellation point. - /// \param CR Cancellation region. - void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; } - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// - static OMPCancellationPointDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// - static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C, - EmptyShell); - - /// \brief Get cancellation region for the current cancellation point. - OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPCancellationPointDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp cancel' directive. -/// -/// \code -/// #pragma omp cancel for -/// \endcode -/// -/// In this example a cancel is created for innermost 'for' region. -class OMPCancelDirective : public OMPExecutableDirective { - friend class ASTStmtReader; - OpenMPDirectiveKind CancelRegion; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param NumClauses Number of clauses. - /// - OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses) - : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, - StartLoc, EndLoc, NumClauses, 0), - CancelRegion(OMPD_unknown) {} - - /// \brief Build an empty directive. - /// - /// \param NumClauses Number of clauses. - explicit OMPCancelDirective(unsigned NumClauses) - : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, - SourceLocation(), SourceLocation(), NumClauses, - 0), - CancelRegion(OMPD_unknown) {} - - /// \brief Set cancel region for current cancellation point. - /// \param CR Cancellation region. - void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; } - -public: - /// \brief Creates directive. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// - static OMPCancelDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion); - - /// \brief Creates an empty directive. - /// - /// \param C AST context. - /// \param NumClauses Number of clauses. - /// - static OMPCancelDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, EmptyShell); - - /// \brief Get cancellation region for the current cancellation point. - OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPCancelDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp taskloop' directive. -/// -/// \code -/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num) -/// \endcode -/// In this example directive '#pragma omp taskloop' has clauses 'private' -/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and -/// 'num_tasks' with expression 'num'. -/// -class OMPTaskLoopDirective : public OMPLoopDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop, - StartLoc, EndLoc, CollapsedNum, NumClauses) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop, - SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPTaskLoopDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskLoopDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp taskloop simd' directive. -/// -/// \code -/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num) -/// \endcode -/// In this example directive '#pragma omp taskloop simd' has clauses 'private' -/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and -/// 'num_tasks' with expression 'num'. -/// -class OMPTaskLoopSimdDirective : public OMPLoopDirective { - friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass, - OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum, - NumClauses) {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass, - OMPD_taskloop_simd, SourceLocation(), SourceLocation(), - CollapsedNum, NumClauses) {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPTaskLoopSimdDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, - EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass; - } -}; - -/// \brief This represents '#pragma omp distribute' directive. -/// -/// \code -/// #pragma omp distribute private(a,b) -/// \endcode -/// In this example directive '#pragma omp distribute' has clauses 'private' -/// with the variables 'a' and 'b' -/// -class OMPDistributeDirective : public OMPLoopDirective { - friend class ASTStmtReader; - - /// \brief Build directive with the given start and end location. - /// - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending location of the directive. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute, - StartLoc, EndLoc, CollapsedNum, NumClauses) - {} - - /// \brief Build an empty directive. - /// - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute, - SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) - {} - -public: - /// \brief Creates directive with a list of \a Clauses. - /// - /// \param C AST context. - /// \param StartLoc Starting location of the directive kind. - /// \param EndLoc Ending Location of the directive. - /// \param CollapsedNum Number of collapsed loops. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement, associated with the directive. - /// \param Exprs Helper expressions for CodeGen. - /// - static OMPDistributeDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); - - /// \brief Creates an empty directive with the place - /// for \a NumClauses clauses. - /// - /// \param C AST context. - /// \param CollapsedNum Number of collapsed nested loops. - /// \param NumClauses Number of clauses. - /// - static OMPDistributeDirective *CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, EmptyShell); - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPDistributeDirectiveClass; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h deleted file mode 100644 index df4a2d8..0000000 --- a/include/clang/AST/StmtVisitor.h +++ /dev/null @@ -1,227 +0,0 @@ -//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- 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 StmtVisitor and ConstStmtVisitor interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_STMTVISITOR_H -#define LLVM_CLANG_AST_STMTVISITOR_H - -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtOpenMP.h" - -namespace clang { - -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; - -/// StmtVisitorBase - This class implements a simple visitor for Stmt -/// subclasses. Since Expr derives from Stmt, this also includes support for -/// visiting Exprs. -template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> -class StmtVisitorBase { -public: - -#define PTR(CLASS) typename Ptr<CLASS>::type -#define DISPATCH(NAME, CLASS) \ - return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S)) - - RetTy Visit(PTR(Stmt) S) { - - // If we have a binary expr, dispatch to the subcode of the binop. A smart - // optimizer (e.g. LLVM) will fold this comparison into the switch stmt - // below. - if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) { - switch (BinOp->getOpcode()) { - case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); - case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); - case BO_Mul: DISPATCH(BinMul, BinaryOperator); - case BO_Div: DISPATCH(BinDiv, BinaryOperator); - case BO_Rem: DISPATCH(BinRem, BinaryOperator); - case BO_Add: DISPATCH(BinAdd, BinaryOperator); - case BO_Sub: DISPATCH(BinSub, BinaryOperator); - case BO_Shl: DISPATCH(BinShl, BinaryOperator); - case BO_Shr: DISPATCH(BinShr, BinaryOperator); - - case BO_LT: DISPATCH(BinLT, BinaryOperator); - case BO_GT: DISPATCH(BinGT, BinaryOperator); - case BO_LE: DISPATCH(BinLE, BinaryOperator); - case BO_GE: DISPATCH(BinGE, BinaryOperator); - case BO_EQ: DISPATCH(BinEQ, BinaryOperator); - case BO_NE: DISPATCH(BinNE, BinaryOperator); - - case BO_And: DISPATCH(BinAnd, BinaryOperator); - case BO_Xor: DISPATCH(BinXor, BinaryOperator); - case BO_Or : DISPATCH(BinOr, BinaryOperator); - case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator); - case BO_LOr : DISPATCH(BinLOr, BinaryOperator); - case BO_Assign: DISPATCH(BinAssign, BinaryOperator); - case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator); - case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator); - case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator); - case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator); - case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator); - case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator); - case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator); - case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator); - case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator); - case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator); - case BO_Comma: DISPATCH(BinComma, BinaryOperator); - } - } else if (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) { - switch (UnOp->getOpcode()) { - case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator); - case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator); - case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator); - case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator); - case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); - case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator); - case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator); - case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator); - case UO_Not: DISPATCH(UnaryNot, UnaryOperator); - case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator); - case UO_Real: DISPATCH(UnaryReal, UnaryOperator); - case UO_Imag: DISPATCH(UnaryImag, UnaryOperator); - case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator); - case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator); - } - } - - // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. - switch (S->getStmtClass()) { - default: llvm_unreachable("Unknown stmt kind!"); -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); -#include "clang/AST/StmtNodes.inc" - } - } - - // If the implementation chooses not to implement a certain visit method, fall - // back on VisitExpr or whatever else is the superclass. -#define STMT(CLASS, PARENT) \ - RetTy Visit ## CLASS(PTR(CLASS) S) { DISPATCH(PARENT, PARENT); } -#include "clang/AST/StmtNodes.inc" - - // If the implementation doesn't implement binary operator methods, fall back - // on VisitBinaryOperator. -#define BINOP_FALLBACK(NAME) \ - RetTy VisitBin ## NAME(PTR(BinaryOperator) S) { \ - DISPATCH(BinaryOperator, BinaryOperator); \ - } - BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) - BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) - BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) - BINOP_FALLBACK(Shr) - - BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) - BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) - BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) - BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) - - BINOP_FALLBACK(Assign) - BINOP_FALLBACK(Comma) -#undef BINOP_FALLBACK - - // If the implementation doesn't implement compound assignment operator - // methods, fall back on VisitCompoundAssignOperator. -#define CAO_FALLBACK(NAME) \ - RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S) { \ - DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \ - } - CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) - CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) - CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) - CAO_FALLBACK(XorAssign) -#undef CAO_FALLBACK - - // If the implementation doesn't implement unary operator methods, fall back - // on VisitUnaryOperator. -#define UNARYOP_FALLBACK(NAME) \ - RetTy VisitUnary ## NAME(PTR(UnaryOperator) S) { \ - DISPATCH(UnaryOperator, UnaryOperator); \ - } - UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) - UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) - UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) - - UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) - UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) - UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) - UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(Coawait) -#undef UNARYOP_FALLBACK - - // Base case, ignore it. :) - RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); } - -#undef PTR -#undef DISPATCH -}; - -/// StmtVisitor - This class implements a simple visitor for Stmt subclasses. -/// Since Expr derives from Stmt, this also includes support for visiting Exprs. -/// -/// This class does not preserve constness of Stmt pointers (see also -/// ConstStmtVisitor). -template<typename ImplClass, typename RetTy=void> -class StmtVisitor - : public StmtVisitorBase<make_ptr, ImplClass, RetTy> {}; - -/// ConstStmtVisitor - This class implements a simple visitor for Stmt -/// subclasses. Since Expr derives from Stmt, this also includes support for -/// visiting Exprs. -/// -/// This class preserves constness of Stmt pointers (see also StmtVisitor). -template<typename ImplClass, typename RetTy=void> -class ConstStmtVisitor - : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {}; - -/// \brief This class implements a simple visitor for OMPClause -/// subclasses. -template<class ImplClass, template <typename> class Ptr, typename RetTy> -class OMPClauseVisitorBase { -public: -#define PTR(CLASS) typename Ptr<CLASS>::type -#define DISPATCH(CLASS) \ - return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S)) - -#define OPENMP_CLAUSE(Name, Class) \ - RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); } -#include "clang/Basic/OpenMPKinds.def" - - RetTy Visit(PTR(OMPClause) S) { - // Top switch clause: visit each OMPClause. - switch (S->getClauseKind()) { - default: llvm_unreachable("Unknown clause kind!"); -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S)); -#include "clang/Basic/OpenMPKinds.def" - } - } - // Base case, ignore it. :) - RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); } -#undef PTR -#undef DISPATCH -}; - -template<class ImplClass, typename RetTy = void> -class OMPClauseVisitor : - public OMPClauseVisitorBase <ImplClass, make_ptr, RetTy> {}; -template<class ImplClass, typename RetTy = void> -class ConstOMPClauseVisitor : - public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h deleted file mode 100644 index f87171a..0000000 --- a/include/clang/AST/TemplateBase.h +++ /dev/null @@ -1,661 +0,0 @@ -//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides definitions which are common for all kinds of -// template representation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H -#define LLVM_CLANG_AST_TEMPLATEBASE_H - -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TrailingObjects.h" - -namespace llvm { - class FoldingSetNodeID; -} - -namespace clang { - -class DiagnosticBuilder; -class Expr; -struct PrintingPolicy; -class TypeSourceInfo; -class ValueDecl; - -/// \brief Represents a template argument. -class TemplateArgument { -public: - /// \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. - Null = 0, - /// The template argument is a type. - Type, - /// The template argument is a declaration that was provided for a pointer, - /// reference, or pointer to member non-type template parameter. - Declaration, - /// The template argument is a null pointer or null pointer to member that - /// was provided for a non-type template parameter. - NullPtr, - /// The template argument is an integral value stored in an llvm::APSInt - /// that was provided for an integral non-type template parameter. - Integral, - /// 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 an expression, and we've not resolved it to one - /// of the other forms yet, either because it's dependent or because we're - /// representing a non-canonical template argument (for instance, in a - /// TemplateSpecializationType). Also used to represent a non-dependent - /// __uuidof expression (a Microsoft extension). - Expression, - /// The template argument is actually a parameter pack. Arguments are stored - /// in the Args struct. - Pack - }; - -private: - /// \brief The kind of template argument we're storing. - - struct DA { - unsigned Kind; - void *QT; - ValueDecl *D; - }; - struct I { - unsigned Kind; - // We store a decomposed APSInt with the data allocated by ASTContext if - // BitWidth > 64. The memory may be shared between multiple - // TemplateArgument instances. - unsigned BitWidth : 31; - unsigned IsUnsigned : 1; - union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - const uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; - void *Type; - }; - struct A { - unsigned Kind; - unsigned NumArgs; - const TemplateArgument *Args; - }; - struct TA { - unsigned Kind; - unsigned NumExpansions; - void *Name; - }; - struct TV { - unsigned Kind; - uintptr_t V; - }; - union { - struct DA DeclArg; - struct I Integer; - struct A Args; - struct TA TemplateArg; - struct TV TypeOrValue; - }; - - TemplateArgument(TemplateName, bool) = delete; - -public: - /// \brief Construct an empty, invalid template argument. - TemplateArgument() { - TypeOrValue.Kind = Null; - TypeOrValue.V = 0; - } - - /// \brief Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false) { - TypeOrValue.Kind = isNullPtr ? NullPtr : Type; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); - } - - /// \brief Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. - TemplateArgument(ValueDecl *D, QualType QT) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; - } - - /// \brief Construct an integral constant template argument. The memory to - /// store the value is allocated with Ctx. - TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); - - /// \brief Construct an integral constant template argument with the same - /// value as Other but a different type. - TemplateArgument(const TemplateArgument &Other, QualType Type) { - Integer = Other.Integer; - Integer.Type = Type.getAsOpaquePtr(); - } - - /// \brief Construct a template argument that is a template. - /// - /// 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. - TemplateArgument(TemplateName Name) { - TemplateArg.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, Optional<unsigned> NumExpansions) { - TemplateArg.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 - /// lists used for dependent types and for expression; it will not - /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E) { - TypeOrValue.Kind = Expression; - TypeOrValue.V = 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. - explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { - this->Args.Kind = Pack; - this->Args.Args = Args.data(); - this->Args.NumArgs = Args.size(); - } - - static TemplateArgument getEmptyPack() { return TemplateArgument(None); } - - /// \brief Create a new template argument pack by copying the given set of - /// template arguments. - static TemplateArgument CreatePackCopy(ASTContext &Context, - ArrayRef<TemplateArgument> Args); - - /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } - - /// \brief Determine whether this template argument has no value. - bool isNull() const { return getKind() == Null; } - - /// \brief Whether this template argument is dependent on a template - /// parameter such that its result can change from one instantiation to - /// another. - bool isDependent() const; - - /// \brief Whether this template argument is dependent on a template - /// parameter. - bool isInstantiationDependent() 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 type for a type template argument. - QualType getAsType() const { - assert(getKind() == Type && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); - } - - /// \brief Retrieve the declaration for a declaration non-type - /// template argument. - ValueDecl *getAsDecl() const { - assert(getKind() == Declaration && "Unexpected kind"); - return DeclArg.D; - } - - QualType getParamTypeForDecl() const { - assert(getKind() == Declaration && "Unexpected kind"); - return QualType::getFromOpaquePtr(DeclArg.QT); - } - - /// \brief Retrieve the type for null non-type template argument. - QualType getNullPtrType() const { - assert(getKind() == NullPtr && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); - } - - /// \brief Retrieve the template name for a template name argument. - TemplateName getAsTemplate() const { - assert(getKind() == Template && "Unexpected kind"); - 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 { - assert((getKind() == Template || getKind() == TemplateExpansion) && - "Unexpected kind"); - - return TemplateName::getFromVoidPointer(TemplateArg.Name); - } - - /// \brief Retrieve the number of expansions that a template template argument - /// expansion will produce, if known. - Optional<unsigned> getNumTemplateExpansions() const; - - /// \brief Retrieve the template argument as an integral value. - // FIXME: Provide a way to read the integral data without copying the value. - llvm::APSInt getAsIntegral() const { - assert(getKind() == Integral && "Unexpected kind"); - using namespace llvm; - if (Integer.BitWidth <= 64) - return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); - - unsigned NumWords = APInt::getNumWords(Integer.BitWidth); - return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), - Integer.IsUnsigned); - } - - /// \brief Retrieve the type of the integral value. - QualType getIntegralType() const { - assert(getKind() == Integral && "Unexpected kind"); - return QualType::getFromOpaquePtr(Integer.Type); - } - - void setIntegralType(QualType T) { - assert(getKind() == Integral && "Unexpected kind"); - Integer.Type = T.getAsOpaquePtr(); - } - - /// \brief Retrieve the template argument as an expression. - Expr *getAsExpr() const { - assert(getKind() == Expression && "Unexpected kind"); - return reinterpret_cast<Expr *>(TypeOrValue.V); - } - - /// \brief Iterator that traverses the elements of a template argument pack. - typedef const TemplateArgument * pack_iterator; - - /// \brief Iterator referencing the first argument of a template argument - /// pack. - pack_iterator pack_begin() const { - assert(getKind() == Pack); - return Args.Args; - } - - /// \brief Iterator referencing one past the last argument of a template - /// argument pack. - pack_iterator pack_end() const { - assert(getKind() == Pack); - return Args.Args + Args.NumArgs; - } - - /// \brief Iterator range referencing all of the elements of a template - /// argument pack. - llvm::iterator_range<pack_iterator> pack_elements() const { - return llvm::make_range(pack_begin(), pack_end()); - } - - /// \brief The number of template arguments in the given template argument - /// pack. - unsigned pack_size() const { - assert(getKind() == Pack); - return Args.NumArgs; - } - - /// \brief Return the array of arguments in this template argument pack. - ArrayRef<TemplateArgument> getPackAsArray() const { - assert(getKind() == Pack); - return llvm::makeArrayRef(Args.Args, Args.NumArgs); - } - - /// \brief Determines whether two template arguments are superficially the - /// same. - bool structurallyEquals(const TemplateArgument &Other) const; - - /// \brief When the template argument is a pack expansion, returns - /// the pattern of the pack expansion. - TemplateArgument getPackExpansionPattern() const; - - /// \brief Print this template argument to the given output stream. - void print(const PrintingPolicy &Policy, raw_ostream &Out) const; - - /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; -}; - -/// Location information for a TemplateArgument. -struct TemplateArgumentLocInfo { -private: - - struct T { - // FIXME: We'd like to just use the qualifier in the TemplateName, - // but template arguments get canonicalized too quickly. - NestedNameSpecifier *Qualifier; - void *QualifierLocData; - unsigned TemplateNameLoc; - unsigned EllipsisLoc; - }; - - union { - struct T Template; - Expr *Expression; - TypeSourceInfo *Declarator; - }; - -public: - TemplateArgumentLocInfo(); - - TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} - - TemplateArgumentLocInfo(Expr *E) : Expression(E) {} - - TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateNameLoc, - SourceLocation EllipsisLoc) - { - Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); - Template.QualifierLocData = QualifierLoc.getOpaqueData(); - Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); - Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); - } - - TypeSourceInfo *getAsTypeSourceInfo() const { - return Declarator; - } - - Expr *getAsExpr() const { - return Expression; - } - - NestedNameSpecifierLoc getTemplateQualifierLoc() const { - return NestedNameSpecifierLoc(Template.Qualifier, - Template.QualifierLocData); - } - - SourceLocation getTemplateNameLoc() const { - return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); - } - - SourceLocation getTemplateEllipsisLoc() const { - return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); - } -}; - -/// Location wrapper for a TemplateArgument. TemplateArgument is to -/// TemplateArgumentLoc as Type is to TypeLoc. -class TemplateArgumentLoc { - TemplateArgument Argument; - TemplateArgumentLocInfo LocInfo; - -public: - TemplateArgumentLoc() {} - - TemplateArgumentLoc(const TemplateArgument &Argument, - TemplateArgumentLocInfo Opaque) - : Argument(Argument), LocInfo(Opaque) { - } - - TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) - : Argument(Argument), LocInfo(TInfo) { - assert(Argument.getKind() == TemplateArgument::Type); - } - - TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) - : Argument(Argument), LocInfo(E) { - assert(Argument.getKind() == TemplateArgument::Expression); - } - - TemplateArgumentLoc(const TemplateArgument &Argument, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateNameLoc, - SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), LocInfo(QualifierLoc, 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 || - Argument.getKind() == TemplateArgument::TemplateExpansion) - return getTemplateNameLoc(); - - return getSourceRange().getBegin(); - } - - /// \brief - Fetches the full source range of the argument. - SourceRange getSourceRange() const LLVM_READONLY; - - const TemplateArgument &getArgument() const { - return Argument; - } - - TemplateArgumentLocInfo getLocInfo() const { - return LocInfo; - } - - TypeSourceInfo *getTypeSourceInfo() const { - assert(Argument.getKind() == TemplateArgument::Type); - return LocInfo.getAsTypeSourceInfo(); - } - - Expr *getSourceExpression() const { - assert(Argument.getKind() == TemplateArgument::Expression); - return LocInfo.getAsExpr(); - } - - Expr *getSourceDeclExpression() const { - assert(Argument.getKind() == TemplateArgument::Declaration); - return LocInfo.getAsExpr(); - } - - Expr *getSourceNullPtrExpression() const { - assert(Argument.getKind() == TemplateArgument::NullPtr); - return LocInfo.getAsExpr(); - } - - Expr *getSourceIntegralExpression() const { - assert(Argument.getKind() == TemplateArgument::Integral); - return LocInfo.getAsExpr(); - } - - NestedNameSpecifierLoc getTemplateQualifierLoc() const { - assert(Argument.getKind() == TemplateArgument::Template || - Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateQualifierLoc(); - } - - SourceLocation getTemplateNameLoc() const { - assert(Argument.getKind() == TemplateArgument::Template || - Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateNameLoc(); - } - - SourceLocation getTemplateEllipsisLoc() const { - assert(Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateEllipsisLoc(); - } -}; - -/// A convenient class for passing around template argument -/// information. Designed to be passed by reference. -class TemplateArgumentListInfo { - SmallVector<TemplateArgumentLoc, 8> Arguments; - SourceLocation LAngleLoc; - SourceLocation RAngleLoc; - - // This can leak if used in an AST node, use ASTTemplateArgumentListInfo - // instead. - void *operator new(size_t bytes, ASTContext &C) = delete; - -public: - TemplateArgumentListInfo() {} - - TemplateArgumentListInfo(SourceLocation LAngleLoc, - SourceLocation RAngleLoc) - : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} - - SourceLocation getLAngleLoc() const { return LAngleLoc; } - SourceLocation getRAngleLoc() const { return RAngleLoc; } - - void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } - void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } - - unsigned size() const { return Arguments.size(); } - - const TemplateArgumentLoc *getArgumentArray() const { - return Arguments.data(); - } - - llvm::ArrayRef<TemplateArgumentLoc> arguments() const { - return Arguments; - } - - const TemplateArgumentLoc &operator[](unsigned I) const { - return Arguments[I]; - } - - TemplateArgumentLoc &operator[](unsigned I) { - return Arguments[I]; - } - - void addArgument(const TemplateArgumentLoc &Loc) { - Arguments.push_back(Loc); - } -}; - -/// \brief Represents an explicit template argument list in C++, e.g., -/// the "<int>" in "sort<int>". -/// This is safe to be used inside an AST node, in contrast with -/// TemplateArgumentListInfo. -struct ASTTemplateArgumentListInfo final - : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, - TemplateArgumentLoc> { -private: - friend TrailingObjects; - - ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); - -public: - /// \brief The source location of the left angle bracket ('<'). - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'). - SourceLocation RAngleLoc; - - /// \brief The number of template arguments in TemplateArgs. - unsigned NumTemplateArgs; - - /// \brief Retrieve the template arguments - const TemplateArgumentLoc *getTemplateArgs() const { - return getTrailingObjects<TemplateArgumentLoc>(); - } - - const TemplateArgumentLoc &operator[](unsigned I) const { - return getTemplateArgs()[I]; - } - - static const ASTTemplateArgumentListInfo * - Create(ASTContext &C, const TemplateArgumentListInfo &List); -}; - -/// \brief Represents an explicit template argument list in C++, e.g., -/// the "<int>" in "sort<int>". -/// -/// It is intended to be used as a trailing object on AST nodes, and -/// as such, doesn't contain the array of TemplateArgumentLoc itself, -/// but expects the containing object to also provide storage for -/// that. -struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo { - /// \brief The source location of the left angle bracket ('<'). - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'). - SourceLocation RAngleLoc; - - /// \brief The source location of the template keyword; this is used - /// as part of the representation of qualified identifiers, such as - /// S<T>::template apply<T>. Will be empty if this expression does - /// not have a template keyword. - SourceLocation TemplateKWLoc; - - /// \brief The number of template arguments in TemplateArgs. - unsigned NumTemplateArgs; - - void initializeFrom(SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &List, - TemplateArgumentLoc *OutArgArray); - void initializeFrom(SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &List, - TemplateArgumentLoc *OutArgArray, bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack); - void initializeFrom(SourceLocation TemplateKWLoc); - - void copyInto(const TemplateArgumentLoc *ArgArray, - TemplateArgumentListInfo &List) const; -}; - -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const TemplateArgument &Arg); - -inline TemplateSpecializationType::iterator - TemplateSpecializationType::end() const { - return getArgs() + getNumArgs(); -} - -inline DependentTemplateSpecializationType::iterator - DependentTemplateSpecializationType::end() const { - return getArgs() + getNumArgs(); -} - -inline const TemplateArgument & - TemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - -inline const TemplateArgument & - DependentTemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - -} // end namespace clang - -#endif diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h deleted file mode 100644 index 3e10d2f..0000000 --- a/include/clang/AST/TemplateName.h +++ /dev/null @@ -1,533 +0,0 @@ -//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the TemplateName interface and subclasses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TEMPLATENAME_H -#define LLVM_CLANG_AST_TEMPLATENAME_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerUnion.h" - -namespace clang { - -class ASTContext; -class DependentTemplateName; -class DiagnosticBuilder; -class IdentifierInfo; -class NamedDecl; -class NestedNameSpecifier; -enum OverloadedOperatorKind : int; -class OverloadedTemplateStorage; -struct PrintingPolicy; -class QualifiedTemplateName; -class SubstTemplateTemplateParmPackStorage; -class SubstTemplateTemplateParmStorage; -class TemplateArgument; -class TemplateDecl; -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: - enum Kind { - Overloaded, - SubstTemplateTemplateParm, - SubstTemplateTemplateParmPack - }; - - struct BitsTag { - /// \brief A Kind. - unsigned Kind : 2; - - /// \brief The number of stored templates or template arguments, - /// depending on which subclass we have. - unsigned Size : 30; - }; - - union { - struct BitsTag Bits; - void *PointerAlignment; - }; - - UncommonTemplateNameStorage(Kind kind, unsigned size) { - Bits.Kind = kind; - Bits.Size = size; - } - -public: - unsigned size() const { return Bits.Size; } - - OverloadedTemplateStorage *getAsOverloadedStorage() { - return Bits.Kind == Overloaded - ? reinterpret_cast<OverloadedTemplateStorage *>(this) - : nullptr; - } - - SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() { - return Bits.Kind == SubstTemplateTemplateParm - ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this) - : nullptr; - } - - SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() { - return Bits.Kind == SubstTemplateTemplateParmPack - ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) - : nullptr; - } -}; - -/// \brief A structure for storing the information associated with an -/// overloaded template name. -class OverloadedTemplateStorage : public UncommonTemplateNameStorage { - friend class ASTContext; - - OverloadedTemplateStorage(unsigned size) - : UncommonTemplateNameStorage(Overloaded, size) { } - - NamedDecl **getStorage() { - return reinterpret_cast<NamedDecl **>(this + 1); - } - NamedDecl * const *getStorage() const { - return reinterpret_cast<NamedDecl *const *>(this + 1); - } - -public: - typedef NamedDecl *const *iterator; - - 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 -{ - TemplateTemplateParmDecl *Parameter; - const TemplateArgument *Arguments; - -public: - SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, - unsigned Size, - const TemplateArgument *Arguments) - : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), - 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, ASTContext &Context); - - static void Profile(llvm::FoldingSetNodeID &ID, - ASTContext &Context, - TemplateTemplateParmDecl *Parameter, - const TemplateArgument &ArgPack); -}; - -/// \brief Represents a C++ template name within the type system. -/// -/// A C++ template name refers to a template within the C++ type -/// system. In most cases, a template name is simply a reference to a -/// class template, e.g. -/// -/// \code -/// template<typename T> class X { }; -/// -/// X<int> xi; -/// \endcode -/// -/// Here, the 'X' in \c X<int> is a template name that refers to the -/// declaration of the class template X, above. Template names can -/// also refer to function templates, C++0x template aliases, etc. -/// -/// Some template names are dependent. For example, consider: -/// -/// \code -/// template<typename MetaFun, typename T1, typename T2> struct apply2 { -/// typedef typename MetaFun::template apply<T1, T2>::type type; -/// }; -/// \endcode -/// -/// Here, "apply" is treated as a template name within the typename -/// specifier in the typedef. "apply" is a nested template, and can -/// only be understood in the context of -class TemplateName { - typedef llvm::PointerUnion4<TemplateDecl *, - UncommonTemplateNameStorage *, - QualifiedTemplateName *, - DependentTemplateName *> StorageType; - - StorageType Storage; - - explicit TemplateName(void *Ptr); - -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, - /// \brief A dependent template name that has not been resolved to a - /// template (or set of templates). - DependentTemplate, - /// \brief A template template parameter that has been substituted - /// for some other template name. - SubstTemplateTemplateParm, - /// \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); - explicit TemplateName(OverloadedTemplateStorage *Storage); - explicit TemplateName(SubstTemplateTemplateParmStorage *Storage); - explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage); - explicit TemplateName(QualifiedTemplateName *Qual); - explicit TemplateName(DependentTemplateName *Dep); - - /// \brief Determine whether this template name is NULL. - bool isNull() const; - - // \brief Get the kind of name that is actually stored. - NameKind getKind() const; - - /// \brief Retrieve the underlying template declaration that - /// this template name refers to, if known. - /// - /// \returns The template declaration that this template name refers - /// to, if any. If the template name does not refer to a specific - /// declaration because it is a dependent name, or if it refers to a - /// set of function templates, returns NULL. - TemplateDecl *getAsTemplateDecl() const; - - /// \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 - /// name refers to, if known. If the template name does not refer to a - /// specific set of function templates because it is a dependent name or - /// refers to a single template, returns NULL. - OverloadedTemplateStorage *getAsOverloadedTemplate() const; - - /// \brief Retrieve the substituted template template parameter, if - /// known. - /// - /// \returns The storage for the substituted template template parameter, - /// if known. Otherwise, returns NULL. - SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const; - - /// \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; - - /// \brief Retrieve the underlying qualified template name - /// structure, if any. - QualifiedTemplateName *getAsQualifiedTemplateName() const; - - /// \brief Retrieve the underlying dependent template name - /// structure, if any. - DependentTemplateName *getAsDependentTemplateName() const; - - TemplateName getUnderlying() const; - - /// \brief Determines whether this is a dependent template name. - bool isDependent() const; - - /// \brief Determines whether this is a template name that somehow - /// depends on a template parameter. - bool isInstantiationDependent() 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 - /// printed. - /// - /// \param SuppressNNS if true, don't print the - /// nested-name-specifier that precedes the template name (if it has - /// one). - void print(raw_ostream &OS, const PrintingPolicy &Policy, - bool SuppressNNS = false) const; - - /// \brief Debugging aid that dumps the template name. - void dump(raw_ostream &OS) const; - - /// \brief Debugging aid that dumps the template name to standard - /// error. - void dump() const; - - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddPointer(Storage.getOpaqueValue()); - } - - /// \brief Retrieve the template name as a void pointer. - void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } - - /// \brief Build a template name from a void pointer. - static TemplateName getFromVoidPointer(void *Ptr) { - return TemplateName(Ptr); - } -}; - -/// Insertion operator for diagnostics. This allows sending TemplateName's -/// into a diagnostic with <<. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - TemplateName N); - -/// \brief A structure for storing the information associated with a -/// substituted template template parameter. -class SubstTemplateTemplateParmStorage - : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { - friend class ASTContext; - - TemplateTemplateParmDecl *Parameter; - TemplateName Replacement; - - SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, - TemplateName replacement) - : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), - Parameter(parameter), Replacement(replacement) {} - -public: - TemplateTemplateParmDecl *getParameter() const { return Parameter; } - TemplateName getReplacement() const { return Replacement; } - - void Profile(llvm::FoldingSetNodeID &ID); - - static void Profile(llvm::FoldingSetNodeID &ID, - TemplateTemplateParmDecl *parameter, - TemplateName replacement); -}; - -inline TemplateName TemplateName::getUnderlying() const { - if (SubstTemplateTemplateParmStorage *subst - = getAsSubstTemplateTemplateParm()) - return subst->getReplacement().getUnderlying(); - return *this; -} - -/// \brief Represents a template name that was expressed as a -/// qualified name. -/// -/// This kind of template name refers to a template name that was -/// preceded by a nested name specifier, e.g., \c std::vector. Here, -/// the nested name specifier is "std::" and the template name is the -/// declaration for "vector". The QualifiedTemplateName class is only -/// used to provide "sugar" for template names that were expressed -/// with a qualified name, and has no semantic meaning. In this -/// manner, it is to TemplateName what ElaboratedType is to Type, -/// providing extra syntactic sugar for downstream clients. -class QualifiedTemplateName : public llvm::FoldingSetNode { - /// \brief The nested name specifier that qualifies the template name. - /// - /// The bit is used to indicate whether the "template" keyword was - /// present before the template name itself. Note that the - /// "template" keyword is always redundant in this case (otherwise, - /// the template name would be a dependent name and we would express - /// this name with DependentTemplateName). - llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; - - /// \brief The template declaration or set of overloaded function templates - /// that this qualified name refers to. - TemplateDecl *Template; - - friend class ASTContext; - - QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - TemplateDecl *Template) - : Qualifier(NNS, TemplateKeyword? 1 : 0), - Template(Template) { } - -public: - /// \brief Return the nested name specifier that qualifies this name. - NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - - /// \brief Whether the template name was prefixed by the "template" - /// keyword. - bool hasTemplateKeyword() const { return Qualifier.getInt(); } - - /// \brief The template declaration that this qualified name refers - /// to. - TemplateDecl *getDecl() const { return Template; } - - /// \brief The template declaration to which this qualified name - /// refers. - TemplateDecl *getTemplateDecl() const { return Template; } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - bool TemplateKeyword, TemplateDecl *Template) { - ID.AddPointer(NNS); - ID.AddBoolean(TemplateKeyword); - ID.AddPointer(Template); - } -}; - -/// \brief Represents a dependent template name that cannot be -/// resolved prior to template instantiation. -/// -/// This kind of template name refers to a dependent template name, -/// including its nested name specifier (if any). For example, -/// DependentTemplateName can refer to "MetaFun::template apply", -/// where "MetaFun::" is the nested name specifier and "apply" is the -/// template name referenced. The "template" keyword is implied. -class DependentTemplateName : public llvm::FoldingSetNode { - /// \brief The nested name specifier that qualifies the template - /// name. - /// - /// The bit stored in this qualifier describes whether the \c Name field - /// is interpreted as an IdentifierInfo pointer (when clear) or as an - /// overloaded operator kind (when set). - llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier; - - /// \brief The dependent template name. - union { - /// \brief The identifier template name. - /// - /// Only valid when the bit on \c Qualifier is clear. - const IdentifierInfo *Identifier; - - /// \brief The overloaded operator name. - /// - /// Only valid when the bit on \c Qualifier is set. - OverloadedOperatorKind Operator; - }; - - /// \brief The canonical template name to which this dependent - /// template name refers. - /// - /// The canonical template name for a dependent template name is - /// another dependent template name whose nested name specifier is - /// canonical. - TemplateName CanonicalTemplateName; - - friend class ASTContext; - - DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Identifier) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(this) { } - - DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Identifier, - TemplateName Canon) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(Canon) { } - - DependentTemplateName(NestedNameSpecifier *Qualifier, - OverloadedOperatorKind Operator) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(this) { } - - DependentTemplateName(NestedNameSpecifier *Qualifier, - OverloadedOperatorKind Operator, - TemplateName Canon) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(Canon) { } - -public: - /// \brief Return the nested name specifier that qualifies this name. - NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - - /// \brief Determine whether this template name refers to an identifier. - bool isIdentifier() const { return !Qualifier.getInt(); } - - /// \brief Returns the identifier to which this template name refers. - const IdentifierInfo *getIdentifier() const { - assert(isIdentifier() && "Template name isn't an identifier?"); - return Identifier; - } - - /// \brief Determine whether this template name refers to an overloaded - /// operator. - bool isOverloadedOperator() const { return Qualifier.getInt(); } - - /// \brief Return the overloaded operator to which this template name refers. - OverloadedOperatorKind getOperator() const { - assert(isOverloadedOperator() && - "Template name isn't an overloaded operator?"); - return Operator; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - if (isIdentifier()) - Profile(ID, getQualifier(), getIdentifier()); - else - Profile(ID, getQualifier(), getOperator()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - const IdentifierInfo *Identifier) { - ID.AddPointer(NNS); - ID.AddBoolean(false); - ID.AddPointer(Identifier); - } - - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) { - ID.AddPointer(NNS); - ID.AddBoolean(true); - ID.AddInteger(Operator); - } -}; - -} // end namespace clang. - -namespace llvm { - -/// \brief The clang::TemplateName class is effectively a pointer. -template<> -class PointerLikeTypeTraits<clang::TemplateName> { -public: - static inline void *getAsVoidPointer(clang::TemplateName TN) { - return TN.getAsVoidPointer(); - } - - static inline clang::TemplateName getFromVoidPointer(void *Ptr) { - return clang::TemplateName::getFromVoidPointer(Ptr); - } - - // No bits are available! - enum { NumLowBitsAvailable = 0 }; -}; - -} // end namespace llvm. - -#endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h deleted file mode 100644 index 0c08130..0000000 --- a/include/clang/AST/Type.h +++ /dev/null @@ -1,5683 +0,0 @@ -//===--- Type.h - C Language Family Type Representation ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// \brief C Language Family Type Representation -/// -/// This file defines the clang::Type interface and subclasses, used to -/// represent types for languages in the C family. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TYPE_H -#define LLVM_CLANG_AST_TYPE_H - -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/TemplateName.h" -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Linkage.h" -#include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/Visibility.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/ErrorHandling.h" - -namespace clang { - enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits - }; - class Type; - class ExtQuals; - class QualType; -} - -namespace llvm { - template <typename T> - class PointerLikeTypeTraits; - template<> - class PointerLikeTypeTraits< ::clang::Type*> { - public: - static inline void *getAsVoidPointer(::clang::Type *P) { return P; } - static inline ::clang::Type *getFromVoidPointer(void *P) { - return static_cast< ::clang::Type*>(P); - } - enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; - }; - template<> - class PointerLikeTypeTraits< ::clang::ExtQuals*> { - public: - static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } - static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { - return static_cast< ::clang::ExtQuals*>(P); - } - enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; - }; - - template <> - struct isPodLike<clang::QualType> { static const bool value = true; }; -} - -namespace clang { - class ASTContext; - class TypedefNameDecl; - class TemplateDecl; - class TemplateTypeParmDecl; - class NonTypeTemplateParmDecl; - class TemplateTemplateParmDecl; - class TagDecl; - class RecordDecl; - class CXXRecordDecl; - class EnumDecl; - class FieldDecl; - class FunctionDecl; - class ObjCInterfaceDecl; - class ObjCProtocolDecl; - class ObjCMethodDecl; - class UnresolvedUsingTypenameDecl; - class Expr; - class Stmt; - class SourceLocation; - class StmtIteratorBase; - class TemplateArgument; - class TemplateArgumentLoc; - class TemplateArgumentListInfo; - class ElaboratedType; - class ExtQuals; - class ExtQualsTypeCommonBase; - struct PrintingPolicy; - - template <typename> class CanQual; - typedef CanQual<Type> CanQualType; - - // Provide forward declarations for all of the *Type classes -#define TYPE(Class, Base) class Class##Type; -#include "clang/AST/TypeNodes.def" - -/// The collection of all-type qualifiers we support. -/// Clang supports five independent qualifiers: -/// * C99: const, volatile, and restrict -/// * Embedded C (TR18037): address spaces -/// * Objective C: the GC attributes (none, weak, or strong) -class Qualifiers { -public: - enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ. - Const = 0x1, - Restrict = 0x2, - Volatile = 0x4, - CVRMask = Const | Volatile | Restrict - }; - - enum GC { - GCNone = 0, - Weak, - Strong - }; - - enum ObjCLifetime { - /// There is no lifetime qualification on this type. - OCL_None, - - /// This object can be modified without requiring retains or - /// releases. - OCL_ExplicitNone, - - /// Assigning into this object requires the old value to be - /// released and the new value to be retained. The timing of the - /// release of the old value is inexact: it may be moved to - /// immediately after the last known point where the value is - /// live. - OCL_Strong, - - /// Reading or writing from this object requires a barrier call. - OCL_Weak, - - /// Assigning into this object requires a lifetime extension. - OCL_Autoreleasing - }; - - enum { - /// The maximum supported address space number. - /// 24 bits should be enough for anyone. - MaxAddressSpace = 0xffffffu, - - /// The width of the "fast" qualifier mask. - FastWidth = 3, - - /// The fast qualifier mask. - FastMask = (1 << FastWidth) - 1 - }; - - Qualifiers() : Mask(0) {} - - /// Returns the common set of qualifiers while removing them from - /// the given sets. - static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { - // If both are only CVR-qualified, bit operations are sufficient. - if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) { - Qualifiers Q; - Q.Mask = L.Mask & R.Mask; - L.Mask &= ~Q.Mask; - R.Mask &= ~Q.Mask; - return Q; - } - - Qualifiers Q; - unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers(); - Q.addCVRQualifiers(CommonCRV); - L.removeCVRQualifiers(CommonCRV); - R.removeCVRQualifiers(CommonCRV); - - if (L.getObjCGCAttr() == R.getObjCGCAttr()) { - Q.setObjCGCAttr(L.getObjCGCAttr()); - L.removeObjCGCAttr(); - R.removeObjCGCAttr(); - } - - if (L.getObjCLifetime() == R.getObjCLifetime()) { - Q.setObjCLifetime(L.getObjCLifetime()); - L.removeObjCLifetime(); - R.removeObjCLifetime(); - } - - if (L.getAddressSpace() == R.getAddressSpace()) { - Q.setAddressSpace(L.getAddressSpace()); - L.removeAddressSpace(); - R.removeAddressSpace(); - } - return Q; - } - - static Qualifiers fromFastMask(unsigned Mask) { - Qualifiers Qs; - Qs.addFastQualifiers(Mask); - return Qs; - } - - static Qualifiers fromCVRMask(unsigned CVR) { - Qualifiers Qs; - Qs.addCVRQualifiers(CVR); - return Qs; - } - - // Deserialize qualifiers from an opaque representation. - static Qualifiers fromOpaqueValue(unsigned opaque) { - Qualifiers Qs; - Qs.Mask = opaque; - return Qs; - } - - // Serialize these qualifiers into an opaque representation. - unsigned getAsOpaqueValue() const { - return Mask; - } - - bool hasConst() const { return Mask & Const; } - void setConst(bool flag) { - Mask = (Mask & ~Const) | (flag ? Const : 0); - } - void removeConst() { Mask &= ~Const; } - void addConst() { Mask |= Const; } - - bool hasVolatile() const { return Mask & Volatile; } - void setVolatile(bool flag) { - Mask = (Mask & ~Volatile) | (flag ? Volatile : 0); - } - void removeVolatile() { Mask &= ~Volatile; } - void addVolatile() { Mask |= Volatile; } - - bool hasRestrict() const { return Mask & Restrict; } - void setRestrict(bool flag) { - Mask = (Mask & ~Restrict) | (flag ? Restrict : 0); - } - void removeRestrict() { Mask &= ~Restrict; } - void addRestrict() { Mask |= Restrict; } - - bool hasCVRQualifiers() const { return getCVRQualifiers(); } - unsigned getCVRQualifiers() const { return Mask & CVRMask; } - void setCVRQualifiers(unsigned mask) { - assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); - Mask = (Mask & ~CVRMask) | mask; - } - void removeCVRQualifiers(unsigned mask) { - assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); - Mask &= ~mask; - } - void removeCVRQualifiers() { - removeCVRQualifiers(CVRMask); - } - void addCVRQualifiers(unsigned mask) { - assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); - Mask |= mask; - } - - bool hasObjCGCAttr() const { return Mask & GCAttrMask; } - GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); } - void setObjCGCAttr(GC type) { - Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift); - } - void removeObjCGCAttr() { setObjCGCAttr(GCNone); } - void addObjCGCAttr(GC type) { - assert(type); - setObjCGCAttr(type); - } - Qualifiers withoutObjCGCAttr() const { - Qualifiers qs = *this; - qs.removeObjCGCAttr(); - return qs; - } - Qualifiers withoutObjCLifetime() const { - Qualifiers qs = *this; - qs.removeObjCLifetime(); - return qs; - } - - bool hasObjCLifetime() const { return Mask & LifetimeMask; } - ObjCLifetime getObjCLifetime() const { - return ObjCLifetime((Mask & LifetimeMask) >> LifetimeShift); - } - void setObjCLifetime(ObjCLifetime type) { - Mask = (Mask & ~LifetimeMask) | (type << LifetimeShift); - } - void removeObjCLifetime() { setObjCLifetime(OCL_None); } - void addObjCLifetime(ObjCLifetime type) { - assert(type); - assert(!hasObjCLifetime()); - Mask |= (type << LifetimeShift); - } - - /// True if the lifetime is neither None or ExplicitNone. - bool hasNonTrivialObjCLifetime() const { - ObjCLifetime lifetime = getObjCLifetime(); - return (lifetime > OCL_ExplicitNone); - } - - /// True if the lifetime is either strong or weak. - bool hasStrongOrWeakObjCLifetime() const { - ObjCLifetime lifetime = getObjCLifetime(); - return (lifetime == OCL_Strong || lifetime == OCL_Weak); - } - - bool hasAddressSpace() const { return Mask & AddressSpaceMask; } - unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } - void setAddressSpace(unsigned space) { - assert(space <= MaxAddressSpace); - Mask = (Mask & ~AddressSpaceMask) - | (((uint32_t) space) << AddressSpaceShift); - } - void removeAddressSpace() { setAddressSpace(0); } - void addAddressSpace(unsigned space) { - assert(space); - setAddressSpace(space); - } - - // Fast qualifiers are those that can be allocated directly - // on a QualType object. - bool hasFastQualifiers() const { return getFastQualifiers(); } - unsigned getFastQualifiers() const { return Mask & FastMask; } - void setFastQualifiers(unsigned mask) { - assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); - Mask = (Mask & ~FastMask) | mask; - } - void removeFastQualifiers(unsigned mask) { - assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); - Mask &= ~mask; - } - void removeFastQualifiers() { - removeFastQualifiers(FastMask); - } - void addFastQualifiers(unsigned mask) { - assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); - Mask |= mask; - } - - /// Return true if the set contains any qualifiers which require an ExtQuals - /// node to be allocated. - bool hasNonFastQualifiers() const { return Mask & ~FastMask; } - Qualifiers getNonFastQualifiers() const { - Qualifiers Quals = *this; - Quals.setFastQualifiers(0); - return Quals; - } - - /// Return true if the set contains any qualifiers. - bool hasQualifiers() const { return Mask; } - bool empty() const { return !Mask; } - - /// Add the qualifiers from the given set to this set. - void addQualifiers(Qualifiers Q) { - // If the other set doesn't have any non-boolean qualifiers, just - // bit-or it in. - if (!(Q.Mask & ~CVRMask)) - Mask |= Q.Mask; - else { - Mask |= (Q.Mask & CVRMask); - if (Q.hasAddressSpace()) - addAddressSpace(Q.getAddressSpace()); - if (Q.hasObjCGCAttr()) - addObjCGCAttr(Q.getObjCGCAttr()); - if (Q.hasObjCLifetime()) - addObjCLifetime(Q.getObjCLifetime()); - } - } - - /// \brief Remove the qualifiers from the given set from this set. - void removeQualifiers(Qualifiers Q) { - // If the other set doesn't have any non-boolean qualifiers, just - // bit-and the inverse in. - if (!(Q.Mask & ~CVRMask)) - Mask &= ~Q.Mask; - else { - Mask &= ~(Q.Mask & CVRMask); - if (getObjCGCAttr() == Q.getObjCGCAttr()) - removeObjCGCAttr(); - if (getObjCLifetime() == Q.getObjCLifetime()) - removeObjCLifetime(); - if (getAddressSpace() == Q.getAddressSpace()) - removeAddressSpace(); - } - } - - /// 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()); - assert(getObjCLifetime() == qs.getObjCLifetime() || - !hasObjCLifetime() || !qs.hasObjCLifetime()); - Mask |= qs.Mask; - } - - /// Returns true if this address space is a superset of the other one. - /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of - /// overlapping address spaces. - /// CL1.1 or CL1.2: - /// every address space is a superset of itself. - /// CL2.0 adds: - /// __generic is a superset of any address space except for __constant. - bool isAddressSpaceSupersetOf(Qualifiers other) const { - return - // Address spaces must match exactly. - getAddressSpace() == other.getAddressSpace() || - // Otherwise in OpenCLC v2.0 s6.5.5: every address space except - // for __constant can be used as __generic. - (getAddressSpace() == LangAS::opencl_generic && - other.getAddressSpace() != LangAS::opencl_constant); - } - - /// 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 { - return isAddressSpaceSupersetOf(other) && - // ObjC GC qualifiers can match, be added, or be removed, but can't - // be changed. - (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || - !other.hasObjCGCAttr()) && - // ObjC lifetime qualifiers must match exactly. - getObjCLifetime() == other.getObjCLifetime() && - // CVR qualifiers may subset. - (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); - } - - /// \brief Determines if these qualifiers compatibly include another set of - /// qualifiers from the narrow perspective of Objective-C ARC lifetime. - /// - /// One set of Objective-C lifetime qualifiers compatibly includes the other - /// if the lifetime qualifiers match, or if both are non-__weak and the - /// including set also contains the 'const' qualifier, or both are non-__weak - /// and one is None (which can only happen in non-ARC modes). - bool compatiblyIncludesObjCLifetime(Qualifiers other) const { - if (getObjCLifetime() == other.getObjCLifetime()) - return true; - - if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak) - return false; - - if (getObjCLifetime() == OCL_None || other.getObjCLifetime() == OCL_None) - return true; - - return hasConst(); - } - - /// \brief Determine whether this set of qualifiers is a strict superset of - /// another set of qualifiers, not considering qualifier compatibility. - bool isStrictSupersetOf(Qualifiers Other) const; - - bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } - bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } - - explicit operator bool() const { return hasQualifiers(); } - - Qualifiers &operator+=(Qualifiers R) { - addQualifiers(R); - return *this; - } - - // Union two qualifier sets. If an enumerated qualifier appears - // in both sets, use the one from the right. - friend Qualifiers operator+(Qualifiers L, Qualifiers R) { - L += R; - return L; - } - - Qualifiers &operator-=(Qualifiers R) { - removeQualifiers(R); - return *this; - } - - /// \brief Compute the difference between two qualifier sets. - friend Qualifiers operator-(Qualifiers L, Qualifiers R) { - L -= R; - return L; - } - - std::string getAsString() const; - std::string getAsString(const PrintingPolicy &Policy) const; - - bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const; - void print(raw_ostream &OS, const PrintingPolicy &Policy, - bool appendSpaceIfNonEmpty = false) const; - - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddInteger(Mask); - } - -private: - - // bits: |0 1 2|3 .. 4|5 .. 7|8 ... 31| - // |C R V|GCAttr|Lifetime|AddressSpace| - uint32_t Mask; - - static const uint32_t GCAttrMask = 0x18; - static const uint32_t GCAttrShift = 3; - static const uint32_t LifetimeMask = 0xE0; - static const uint32_t LifetimeShift = 5; - static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask); - static const uint32_t AddressSpaceShift = 8; -}; - -/// A std::pair-like structure for storing a qualified type split -/// into its local qualifiers and its locally-unqualified type. -struct SplitQualType { - /// The locally-unqualified type. - const Type *Ty; - - /// The local qualifiers. - Qualifiers Quals; - - SplitQualType() : Ty(nullptr), Quals() {} - SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} - - SplitQualType getSingleStepDesugaredType() const; // end of this file - - // Make std::tie work. - std::pair<const Type *,Qualifiers> asPair() const { - return std::pair<const Type *, Qualifiers>(Ty, Quals); - } - - friend bool operator==(SplitQualType a, SplitQualType b) { - return a.Ty == b.Ty && a.Quals == b.Quals; - } - friend bool operator!=(SplitQualType a, SplitQualType b) { - return a.Ty != b.Ty || a.Quals != b.Quals; - } -}; - -/// The kind of type we are substituting Objective-C type arguments into. -/// -/// The kind of substitution affects the replacement of type parameters when -/// no concrete type information is provided, e.g., when dealing with an -/// unspecialized type. -enum class ObjCSubstitutionContext { - /// An ordinary type. - Ordinary, - /// The result type of a method or function. - Result, - /// The parameter type of a method or function. - Parameter, - /// The type of a property. - Property, - /// The superclass of a type. - Superclass, -}; - -/// A (possibly-)qualified type. -/// -/// For efficiency, we don't store CV-qualified types as nodes on their -/// own: instead each reference to a type stores the qualifiers. This -/// greatly reduces the number of nodes we need to allocate for types (for -/// example we only need one for 'int', 'const int', 'volatile int', -/// 'const volatile int', etc). -/// -/// As an added efficiency bonus, instead of making this a pair, we -/// just store the two bits we care about in the low bits of the -/// pointer. To handle the packing/unpacking, we make QualType be a -/// simple wrapper class that acts like a smart pointer. A third bit -/// indicates whether there are extended qualifiers present, in which -/// case the pointer points to a special structure. -class QualType { - // Thankfully, these are efficiently composable. - llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, - Qualifiers::FastWidth> Value; - - const ExtQuals *getExtQualsUnsafe() const { - return Value.getPointer().get<const ExtQuals*>(); - } - - const Type *getTypePtrUnsafe() const { - return Value.getPointer().get<const Type*>(); - } - - 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() {} - - QualType(const Type *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} - QualType(const ExtQuals *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} - - unsigned getLocalFastQualifiers() const { return Value.getInt(); } - void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } - - /// Retrieves a pointer to the underlying (unqualified) type. - /// - /// 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; - - /// Retrieves a pointer to the name of the base type. - const IdentifierInfo *getBaseTypeIdentifier() 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(const void *Ptr) { - QualType T; - T.Value.setFromOpaqueValue(const_cast<void*>(Ptr)); - return T; - } - - const Type &operator*() const { - return *getTypePtr(); - } - - const Type *operator->() const { - return getTypePtr(); - } - - bool isCanonical() const; - bool isCanonicalAsParam() const; - - /// Return true if this QualType doesn't point to a type yet. - bool isNull() const { - return Value.getPointer().isNull(); - } - - /// \brief Determine whether this particular QualType instance has the - /// "const" qualifier set, without looking through typedefs that may have - /// added "const" at a different level. - bool isLocalConstQualified() const { - return (getLocalFastQualifiers() & Qualifiers::Const); - } - - /// \brief Determine whether this type is const-qualified. - bool isConstQualified() const; - - /// \brief Determine whether this particular QualType instance has the - /// "restrict" qualifier set, without looking through typedefs that may have - /// added "restrict" at a different level. - bool isLocalRestrictQualified() const { - return (getLocalFastQualifiers() & Qualifiers::Restrict); - } - - /// \brief Determine whether this type is restrict-qualified. - bool isRestrictQualified() const; - - /// \brief Determine whether this particular QualType instance has the - /// "volatile" qualifier set, without looking through typedefs that may have - /// added "volatile" at a different level. - bool isLocalVolatileQualified() const { - return (getLocalFastQualifiers() & Qualifiers::Volatile); - } - - /// \brief Determine whether this type is volatile-qualified. - bool isVolatileQualified() const; - - /// \brief Determine whether this particular QualType instance has any - /// qualifiers, without looking through any typedefs that might add - /// qualifiers at a different level. - bool hasLocalQualifiers() const { - return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); - } - - /// \brief Determine whether this type has any qualifiers. - bool hasQualifiers() const; - - /// \brief Determine whether this particular QualType instance has any - /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType - /// instance. - bool hasLocalNonFastQualifiers() const { - return Value.getPointer().is<const ExtQuals*>(); - } - - /// \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; - - /// \brief Retrieve the set of qualifiers applied to this type. - Qualifiers getQualifiers() const; - - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers - /// local to this particular QualType instance, not including any qualifiers - /// acquired through typedefs or other sugar. - unsigned getLocalCVRQualifiers() const { - return getLocalFastQualifiers(); - } - - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers - /// applied to this type. - unsigned getCVRQualifiers() const; - - bool isConstant(ASTContext& Ctx) const { - return QualType::isConstant(*this, Ctx); - } - - /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). - bool isPODType(ASTContext &Context) const; - - /// Return true if this is a POD type according to the rules of the C++98 - /// standard, regardless of the current compilation's language. - bool isCXX98PODType(ASTContext &Context) const; - - /// Return true if this is a POD type according to the more relaxed rules - /// of the C++11 standard, regardless of the current compilation's language. - /// (C++0x [basic.types]p9) - bool isCXX11PODType(ASTContext &Context) const; - - /// Return true if this is a trivial type per (C++0x [basic.types]p9) - bool isTrivialType(ASTContext &Context) const; - - /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) - bool isTriviallyCopyableType(ASTContext &Context) const; - - // Don't promise in the API that anything besides 'const' can be - // easily added. - - /// Add the `const` type qualifier to this QualType. - void addConst() { - addFastQualifiers(Qualifiers::Const); - } - QualType withConst() const { - return withFastQualifiers(Qualifiers::Const); - } - - /// Add the `volatile` type qualifier to this QualType. - void addVolatile() { - addFastQualifiers(Qualifiers::Volatile); - } - QualType withVolatile() const { - return withFastQualifiers(Qualifiers::Volatile); - } - - /// Add the `restrict` qualifier to this QualType. - void addRestrict() { - addFastQualifiers(Qualifiers::Restrict); - } - QualType withRestrict() const { - return withFastQualifiers(Qualifiers::Restrict); - } - - QualType withCVRQualifiers(unsigned CVR) const { - return withFastQualifiers(CVR); - } - - void addFastQualifiers(unsigned TQs) { - assert(!(TQs & ~Qualifiers::FastMask) - && "non-fast qualifier bits set in mask!"); - Value.setInt(Value.getInt() | TQs); - } - - void removeLocalConst(); - void removeLocalVolatile(); - void removeLocalRestrict(); - void removeLocalCVRQualifiers(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); - } - - // Creates a type with the given qualifiers in addition to any - // qualifiers already on this type. - QualType withFastQualifiers(unsigned TQs) const { - QualType T = *this; - T.addFastQualifiers(TQs); - return T; - } - - // Creates a type with exactly the given fast qualifiers, removing - // any existing fast qualifiers. - QualType withExactLocalFastQualifiers(unsigned TQs) const { - return withoutLocalFastQualifiers().withFastQualifiers(TQs); - } - - // Removes fast qualifiers, but leaves any extended qualifiers in place. - QualType withoutLocalFastQualifiers() const { - QualType T = *this; - 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 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 sugar for an array - /// type. To strip qualifiers even from within a sugared array type, use - /// ASTContext::getUnqualifiedArrayType. - inline QualType getUnqualifiedType() const; - - /// 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 sugar for an array - /// type. To strip qualifiers even from within a sugared array type, use - /// ASTContext::getUnqualifiedArrayType. - inline SplitQualType getSplitUnqualifiedType() const; - - /// \brief Determine whether this type is more qualified than the other - /// given type, requiring exact equality for non-CVR qualifiers. - bool isMoreQualifiedThan(QualType Other) const; - - /// \brief Determine whether this type is at least as qualified as the other - /// given type, requiring exact equality for non-CVR qualifiers. - bool isAtLeastAsQualifiedAs(QualType Other) const; - - QualType getNonReferenceType() const; - - /// \brief Determine the type of a (typically non-lvalue) expression with the - /// specified result type. - /// - /// This routine should be used for expressions for which the return type is - /// explicitly specified (e.g., in a cast or call) and isn't necessarily - /// an lvalue. It removes a top-level reference (since there are no - /// expressions of reference type) and deletes top-level cvr-qualifiers - /// from non-class types (in C++) or all types (in C). - QualType getNonLValueExprType(const ASTContext &Context) const; - - /// Return the specified type with any "sugar" removed from - /// the type. This takes off typedefs, typeof's etc. If the outer level of - /// the type is already concrete, it returns it unmodified. This is similar - /// to getting the canonical type, but it doesn't remove *all* typedefs. For - /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is - /// concrete. - /// - /// Qualifiers are left in place. - QualType getDesugaredType(const ASTContext &Context) const { - return getDesugaredType(*this, Context); - } - - SplitQualType getSplitDesugaredType() const { - return getSplitDesugaredType(*this); - } - - /// \brief Return the specified type with one level of "sugar" removed from - /// the type. - /// - /// This routine takes off the first typedef, typeof, etc. If the outer level - /// of the type is already concrete, it returns it unmodified. - QualType getSingleStepDesugaredType(const ASTContext &Context) const { - return getSingleStepDesugaredTypeImpl(*this, Context); - } - - /// Returns the specified type after dropping any - /// outer-level parentheses. - QualType IgnoreParens() const { - if (isa<ParenType>(*this)) - return QualType::IgnoreParens(*this); - return *this; - } - - /// Indicate whether the specified types and qualifiers are identical. - friend bool operator==(const QualType &LHS, const QualType &RHS) { - return LHS.Value == RHS.Value; - } - friend bool operator!=(const QualType &LHS, const QualType &RHS) { - return LHS.Value != RHS.Value; - } - std::string getAsString() const { - return getAsString(split()); - } - static std::string getAsString(SplitQualType split) { - return getAsString(split.Ty, split.Quals); - } - static std::string getAsString(const Type *ty, Qualifiers qs); - - std::string getAsString(const PrintingPolicy &Policy) const; - - void print(raw_ostream &OS, const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - print(split(), OS, Policy, PlaceHolder); - } - static void print(SplitQualType split, raw_ostream &OS, - const PrintingPolicy &policy, const Twine &PlaceHolder) { - return print(split.Ty, split.Quals, OS, policy, PlaceHolder); - } - static void print(const Type *ty, Qualifiers qs, - raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder); - - void getAsStringInternal(std::string &Str, - const PrintingPolicy &Policy) const { - return getAsStringInternal(split(), Str, Policy); - } - static void getAsStringInternal(SplitQualType split, std::string &out, - const PrintingPolicy &policy) { - return getAsStringInternal(split.Ty, split.Quals, out, policy); - } - static void getAsStringInternal(const Type *ty, Qualifiers qs, - std::string &out, - const PrintingPolicy &policy); - - class StreamedQualTypeHelper { - const QualType &T; - const PrintingPolicy &Policy; - const Twine &PlaceHolder; - public: - StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, - const Twine &PlaceHolder) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { } - - friend raw_ostream &operator<<(raw_ostream &OS, - const StreamedQualTypeHelper &SQT) { - SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder); - return OS; - } - }; - - StreamedQualTypeHelper stream(const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - return StreamedQualTypeHelper(*this, Policy, PlaceHolder); - } - - void dump(const char *s) const; - void dump() const; - - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddPointer(getAsOpaquePtr()); - } - - /// Return the address space of this type. - inline unsigned getAddressSpace() const; - - /// Returns gc attribute of this type. - inline Qualifiers::GC getObjCGCAttr() const; - - /// true when Type is objc's weak. - bool isObjCGCWeak() const { - return getObjCGCAttr() == Qualifiers::Weak; - } - - /// true when Type is objc's strong. - bool isObjCGCStrong() const { - return getObjCGCAttr() == Qualifiers::Strong; - } - - /// Returns lifetime attribute of this type. - Qualifiers::ObjCLifetime getObjCLifetime() const { - return getQualifiers().getObjCLifetime(); - } - - bool hasNonTrivialObjCLifetime() const { - return getQualifiers().hasNonTrivialObjCLifetime(); - } - - bool hasStrongOrWeakObjCLifetime() const { - return getQualifiers().hasStrongOrWeakObjCLifetime(); - } - - enum DestructionKind { - DK_none, - DK_cxx_destructor, - DK_objc_strong_lifetime, - DK_objc_weak_lifetime - }; - - /// Returns a nonzero value 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); - } - - /// Determine whether expressions of the given type are forbidden - /// from being lvalues in C. - /// - /// The expression types that are forbidden to be lvalues are: - /// - 'void', but not qualified void - /// - function types - /// - /// The exact rule here is C99 6.3.2.1: - /// An lvalue is an expression with an object type or an incomplete - /// type other than void. - bool isCForbiddenLValueType() const; - - /// Substitute type arguments for the Objective-C type parameters used in the - /// subject type. - /// - /// \param ctx ASTContext in which the type exists. - /// - /// \param typeArgs The type arguments that will be substituted for the - /// Objective-C type parameters in the subject type, which are generally - /// computed via \c Type::getObjCSubstitutions. If empty, the type - /// parameters will be replaced with their bounds or id/Class, as appropriate - /// for the context. - /// - /// \param context The context in which the subject type was written. - /// - /// \returns the resulting type. - QualType substObjCTypeArgs(ASTContext &ctx, - ArrayRef<QualType> typeArgs, - ObjCSubstitutionContext context) const; - - /// Substitute type arguments from an object type for the Objective-C type - /// parameters used in the subject type. - /// - /// This operation combines the computation of type arguments for - /// substitution (\c Type::getObjCSubstitutions) with the actual process of - /// substitution (\c QualType::substObjCTypeArgs) for the convenience of - /// callers that need to perform a single substitution in isolation. - /// - /// \param objectType The type of the object whose member type we're - /// substituting into. For example, this might be the receiver of a message - /// or the base of a property access. - /// - /// \param dc The declaration context from which the subject type was - /// retrieved, which indicates (for example) which type parameters should - /// be substituted. - /// - /// \param context The context in which the subject type was written. - /// - /// \returns the subject type after replacing all of the Objective-C type - /// parameters with their corresponding arguments. - QualType substObjCMemberType(QualType objectType, - const DeclContext *dc, - ObjCSubstitutionContext context) const; - - /// Strip Objective-C "__kindof" types from the given type. - QualType stripObjCKindOfType(const ASTContext &ctx) const; - -private: - // These methods are implemented in a separate translation unit; - // "static"-ize them to avoid creating temporary QualTypes in the - // caller. - static bool isConstant(QualType T, ASTContext& Ctx); - static QualType getDesugaredType(QualType T, const ASTContext &Context); - static SplitQualType getSplitDesugaredType(QualType T); - static SplitQualType getSplitUnqualifiedTypeImpl(QualType type); - static QualType getSingleStepDesugaredTypeImpl(QualType type, - const ASTContext &C); - static QualType IgnoreParens(QualType T); - static DestructionKind isDestructedTypeImpl(QualType type); -}; - -} // end clang. - -namespace llvm { -/// Implement simplify_type for QualType, so that we can dyn_cast from QualType -/// to a specific Type class. -template<> struct simplify_type< ::clang::QualType> { - typedef const ::clang::Type *SimpleType; - static SimpleType getSimplifiedValue(::clang::QualType Val) { - return Val.getTypePtr(); - } -}; - -// Teach SmallPtrSet that QualType is "basically a pointer". -template<> -class PointerLikeTypeTraits<clang::QualType> { -public: - static inline void *getAsVoidPointer(clang::QualType P) { - return P.getAsOpaquePtr(); - } - static inline clang::QualType getFromVoidPointer(void *P) { - return clang::QualType::getFromOpaquePtr(P); - } - // Various qualifiers go in low bits. - enum { NumLowBitsAvailable = 0 }; -}; - -} // end namespace llvm - -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; -}; - -/// 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. - - /// 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 hasObjCLifetime() const { return Quals.hasObjCLifetime(); } - Qualifiers::ObjCLifetime getObjCLifetime() const { - return Quals.getObjCLifetime(); - } - - 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); - } -}; - -/// The kind of C++11 ref-qualifier associated with a function type. -/// This 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 -}; - -/// Which keyword(s) were used to create an AutoType. -enum class AutoTypeKeyword { - /// \brief auto - Auto, - /// \brief decltype(auto) - DecltypeAuto, - /// \brief __auto_type (GNU extension) - GNUAutoType -}; - -/// 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 references. For example, consider: -/// -/// typedef int foo; -/// typedef foo* bar; -/// 'int *' 'foo *' 'bar' -/// -/// There will be a Type object created for 'int'. Since int is canonical, its -/// CanonicalType pointer points to itself. There is also a Type for 'foo' (a -/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next -/// there is a PointerType that represents 'int*', which, like 'int', is -/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical -/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type -/// is also 'int*'. -/// -/// Non-canonical types are useful for emitting diagnostics, without losing -/// information about typedefs being used. Canonical types are useful for type -/// comparisons (they allow by-pointer equality tests) and useful for reasoning -/// about whether something has a particular form (e.g. is a function type), -/// because they implicitly, recursively, strip all typedefs out of a type. -/// -/// Types, once created, are immutable. -/// -class Type : public ExtQualsTypeCommonBase { -public: - enum TypeClass { -#define TYPE(Class, Base) Class, -#define LAST_TYPE(Class) TypeLast = Class, -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - TagFirst = Record, TagLast = Enum - }; - -private: - Type(const Type &) = delete; - void operator=(const Type &) = delete; - - /// 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; - - /// Whether this type is a dependent type (C++ [temp.dep.type]). - unsigned Dependent : 1; - - /// Whether this type somehow involves a template parameter, even - /// if the resolution of the type does not depend on a template parameter. - unsigned InstantiationDependent : 1; - - /// 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++11 variadic templates). - unsigned ContainsUnexpandedParameterPack : 1; - - /// \brief True if the cache (i.e. the bitfields here starting with - /// 'Cache') is valid. - mutable unsigned CacheValid : 1; - - /// \brief Linkage of this type. - mutable unsigned CachedLinkage : 3; - - /// \brief Whether this type involves and local or unnamed types. - mutable unsigned CachedLocalOrUnnamed : 1; - - /// \brief Whether this type comes from an AST file. - mutable unsigned FromAST : 1; - - bool isCacheValid() const { - return CacheValid; - } - 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 = 18 }; - -protected: - // These classes allow subclasses to somewhat cleanly pack bitfields - // into Type. - - class ArrayTypeBitfields { - friend class ArrayType; - - unsigned : NumTypeBits; - - /// CVR qualifiers from declarations like - /// 'int X[static restrict 4]'. For function parameters only. - unsigned IndexTypeQuals : 3; - - /// 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; - friend class FunctionProtoType; - - unsigned : NumTypeBits; - - /// Extra information which affects how the function is called, like - /// regparm and the calling convention. - unsigned ExtInfo : 9; - - /// 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; - - /// The number of type arguments stored directly on this object type. - unsigned NumTypeArgs : 7; - - /// The number of protocols stored directly on this object type. - unsigned NumProtocols : 6; - - /// Whether this is a "kindof" type. - unsigned IsKindOf : 1; - }; - static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned"); - - 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; - - /// The kind of vector, either a generic vector type or some - /// target-specific vector type such as for AltiVec or Neon. - unsigned VecKind : 3; - - /// The number of elements in the vector. - unsigned NumElements : 29 - NumTypeBits; - - enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 }; - }; - - class AttributedTypeBitfields { - friend class AttributedType; - - unsigned : NumTypeBits; - - /// An AttributedType::Kind - unsigned AttrKind : 32 - NumTypeBits; - }; - - class AutoTypeBitfields { - friend class AutoType; - - unsigned : NumTypeBits; - - /// Was this placeholder type spelled as 'auto', 'decltype(auto)', - /// or '__auto_type'? AutoTypeKeyword value. - unsigned Keyword : 2; - }; - - union { - TypeBitfields TypeBits; - ArrayTypeBitfields ArrayTypeBits; - AttributedTypeBitfields AttributedTypeBits; - AutoTypeBitfields AutoTypeBits; - 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 { - TypeBits.FromAST = V; - } - - 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 canon, bool Dependent, - bool InstantiationDependent, bool VariablyModified, - bool ContainsUnexpandedParameterPack) - : ExtQualsTypeCommonBase(this, - canon.isNull() ? QualType(this_(), 0) : canon) { - TypeBits.TC = tc; - TypeBits.Dependent = Dependent; - TypeBits.InstantiationDependent = Dependent || InstantiationDependent; - TypeBits.VariablyModified = VariablyModified; - TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; - TypeBits.CacheValid = false; - TypeBits.CachedLocalOrUnnamed = false; - TypeBits.CachedLinkage = NoLinkage; - TypeBits.FromAST = false; - } - friend class ASTContext; - - void setDependent(bool D = true) { - TypeBits.Dependent = D; - if (D) - TypeBits.InstantiationDependent = true; - } - void setInstantiationDependent(bool D = true) { - TypeBits.InstantiationDependent = 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>(TypeBits.TC); } - - /// \brief Whether this type comes from an AST file. - 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 == QualType(this, 0); - } - - /// Pull a single level of sugar off of this locally-unqualified type. - /// Users should generally prefer SplitQualType::getSingleStepDesugaredType() - /// or QualType::getSingleStepDesugaredType(const ASTContext&). - QualType getLocallyUnqualifiedSingleStepDesugaredType() const; - - /// Types are partitioned into 3 broad categories (C99 6.2.5p1): - /// object types, function types, and incomplete types. - - /// Return true if this is an incomplete type. - /// A type that can describe objects, but which lacks information needed to - /// determine its size (e.g. void, or a fwd declared struct). Clients of this - /// routine will need to determine if the size is actually required. - /// - /// \brief Def If non-null, and the type refers to some kind of declaration - /// that can be completed (such as a C struct, C++ class, or Objective-C - /// class), will be set to the declaration. - bool isIncompleteType(NamedDecl **Def = nullptr) const; - - /// Return true if this is an incomplete or object - /// type, in other words, not a function type. - 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(); - } - - /// Return true if this is a literal type - /// (C++11 [basic.types]p10) - bool isLiteralType(const ASTContext &Ctx) const; - - /// Test if this type is a standard-layout type. - /// (C++0x [basic.type]p9) - bool isStandardLayoutType() const; - - /// Helper methods to distinguish type categories. All type predicates - /// operate on the canonical type, ignoring typedefs and qualifiers. - - /// Returns true if the type is a builtin type. - bool isBuiltinType() const; - - /// Test for a particular builtin type. - bool isSpecificBuiltinType(unsigned K) const; - - /// 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; - const BuiltinType *getAsPlaceholderType() const; - - /// Test for a specific placeholder type. - bool isSpecificPlaceholderType(unsigned K) const; - - /// Test for a placeholder type other than Overload; see - /// BuiltinType::isNonOverloadPlaceholderType. - bool isNonOverloadPlaceholderType() 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) - bool isEnumeralType() const; - bool isBooleanType() const; - bool isCharType() const; - bool isWideCharType() const; - bool isChar16Type() const; - bool isChar32Type() const; - bool isAnyCharacterType() const; - bool isIntegralType(ASTContext &Ctx) const; - - /// Determine whether this type is an integral or enumeration type. - bool isIntegralOrEnumerationType() const; - /// 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) - /// isComplexType() does *not* include complex integers (a GCC extension). - /// isComplexIntegerType() can be used to test for complex integers. - bool isComplexType() const; // C99 6.2.5p11 (complex) - bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. - bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) - bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) - bool isRealType() const; // C99 6.2.5p17 (real floating + integer) - bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) - bool isVoidType() const; // C99 6.2.5p19 - bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) - bool isAggregateType() const; - bool isFundamentalType() const; - bool isCompoundType() const; - - // Type Predicates: Check to see if this type is structurally the specified - // type, ignoring typedefs and qualifiers. - bool isFunctionType() const; - bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); } - bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); } - bool isPointerType() const; - bool isAnyPointerType() const; // Any C pointer or ObjC object pointer - bool isBlockPointerType() const; - bool isVoidPointerType() const; - bool isReferenceType() const; - bool isLValueReferenceType() const; - bool isRValueReferenceType() const; - bool isFunctionPointerType() const; - bool isMemberPointerType() const; - bool isMemberFunctionPointerType() const; - bool isMemberDataPointerType() const; - bool isArrayType() const; - bool isConstantArrayType() const; - bool isIncompleteArrayType() const; - bool isVariableArrayType() const; - bool isDependentSizedArrayType() const; - bool isRecordType() const; - bool isClassType() const; - bool isStructureType() const; - bool isObjCBoxableRecordType() const; - bool isInterfaceType() const; - bool isStructureOrClassType() const; - bool isUnionType() const; - bool isComplexIntegerType() const; // GCC _Complex integer type. - bool isVectorType() const; // GCC vector type. - bool isExtVectorType() const; // Extended vector type. - bool isObjCObjectPointerType() const; // pointer to ObjC object - bool isObjCRetainableType() const; // ObjC object or block pointer - bool isObjCLifetimeType() const; // (array of)* retainable type - bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type - bool isObjCNSObjectType() const; // __attribute__((NSObject)) - bool isObjCIndependentClassType() const; // __attribute__((objc_independent_class)) - // FIXME: change this to 'raw' interface type, so we can used 'interface' type - // for the common case. - bool isObjCObjectType() const; // NSString or typeof(*(id)0) - bool isObjCQualifiedInterfaceType() const; // NSString<foo> - bool isObjCQualifiedIdType() const; // id<foo> - bool isObjCQualifiedClassType() const; // Class<foo> - bool isObjCObjectOrInterfaceType() const; - bool isObjCIdType() const; // id - bool isObjCInertUnsafeUnretainedType() const; - - /// Whether the type is Objective-C 'id' or a __kindof type of an - /// object type, e.g., __kindof NSView * or __kindof id - /// <NSCopying>. - /// - /// \param bound Will be set to the bound on non-id subtype types, - /// which will be (possibly specialized) Objective-C class type, or - /// null for 'id. - bool isObjCIdOrObjectKindOfType(const ASTContext &ctx, - const ObjCObjectType *&bound) const; - - bool isObjCClassType() const; // Class - - /// Whether the type is Objective-C 'Class' or a __kindof type of an - /// Class type, e.g., __kindof Class <NSCopying>. - /// - /// Unlike \c isObjCIdOrObjectKindOfType, there is no relevant bound - /// here because Objective-C's type system cannot express "a class - /// object for a subclass of NSFoo". - bool isObjCClassOrClassKindOfType() const; - - bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const; - bool isObjCSelType() const; // Class - bool isObjCBuiltinType() const; // 'id' or 'Class' - bool isObjCARCBridgableType() const; - bool isCARCBridgableType() const; - bool isTemplateTypeParmType() const; // C++ template type parameter - bool isNullPtrType() const; // C++0x nullptr_t - bool isAtomicType() const; // C11 _Atomic() - - bool isImage1dT() const; // OpenCL image1d_t - bool isImage1dArrayT() const; // OpenCL image1d_array_t - bool isImage1dBufferT() const; // OpenCL image1d_buffer_t - bool isImage2dT() const; // OpenCL image2d_t - bool isImage2dArrayT() const; // OpenCL image2d_array_t - bool isImage2dDepthT() const; // OpenCL image_2d_depth_t - bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t - bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t - bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t - bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t - bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t - bool isImage3dT() const; // OpenCL image3d_t - - bool isImageType() const; // Any OpenCL image type - - bool isSamplerT() const; // OpenCL sampler_t - bool isEventT() const; // OpenCL event_t - bool isClkEventT() const; // OpenCL clk_event_t - bool isQueueT() const; // OpenCL queue_t - bool isNDRangeT() const; // OpenCL ndrange_t - bool isReserveIDT() const; // OpenCL reserve_id_t - - bool isOpenCLSpecificType() const; // Any OpenCL specific type - - /// Determines if this type, which must satisfy - /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather - /// than implicitly __strong. - bool isObjCARCImplicitlyUnretainedType() const; - - /// Return the implicit lifetime for this type, which must not be dependent. - Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const; - - enum ScalarTypeKind { - STK_CPointer, - STK_BlockPointer, - STK_ObjCObjectPointer, - STK_MemberPointer, - STK_Bool, - STK_Integral, - STK_Floating, - STK_IntegralComplex, - STK_FloatingComplex - }; - /// Given that this is a scalar type, classify it. - ScalarTypeKind getScalarTypeKind() const; - - /// 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 TypeBits.Dependent; } - - /// \brief Determine whether this type is an instantiation-dependent type, - /// meaning that the type involves a template parameter (even if the - /// definition does not actually depend on the type substituted for that - /// template parameter). - bool isInstantiationDependentType() const { - return TypeBits.InstantiationDependent; - } - - /// \brief Determine whether this type is an undeduced type, meaning that - /// it somehow involves a C++11 'auto' type which has not yet been deduced. - bool isUndeducedType() const; - - /// \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. - bool isElaboratedTypeSpecifier() const; - - bool canDecayToPointerType() const; - - /// Whether this type is represented natively as a pointer. This includes - /// pointers, references, block pointers, and Objective-C interface, - /// qualified id, and qualified interface types, as well as nullptr_t. - bool hasPointerRepresentation() const; - - /// Whether this type can represent an objective pointer type for the - /// purpose of GC'ability - bool hasObjCPointerRepresentation() const; - - /// \brief Determine whether this type has an integer representation - /// of some sort, e.g., it is an integer type or a vector. - bool hasIntegerRepresentation() const; - - /// \brief Determine whether this type has an signed integer representation - /// of some sort, e.g., it is an signed integer type or a vector. - bool hasSignedIntegerRepresentation() const; - - /// \brief Determine whether this type has an unsigned integer representation - /// of some sort, e.g., it is an unsigned integer type or a vector. - bool hasUnsignedIntegerRepresentation() const; - - /// \brief Determine whether this type has a floating-point representation - /// of some sort, e.g., it is a floating-point type or a vector thereof. - bool hasFloatingRepresentation() const; - - // Type Checking Functions: Check to see if this type is structurally the - // specified type, ignoring typedefs and qualifiers, and return a pointer to - // the best type we can. - const RecordType *getAsStructureType() const; - /// NOTE: getAs*ArrayType are methods on ASTContext. - const RecordType *getAsUnionType() const; - const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. - const ObjCObjectType *getAsObjCInterfaceType() const; - // The following is a convenience method that returns an ObjCObjectPointerType - // for object declared using an interface. - const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; - const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; - const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; - const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; - - /// \brief Retrieves the CXXRecordDecl that this type refers to, either - /// 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 Retrieves the TagDecl that this type refers to, either - /// because the type is a TagType or because it is the injected-class-name - /// type of a class template or class template partial specialization. - TagDecl *getAsTagDecl() const; - - /// If this is a pointer or reference to a RecordType, return the - /// CXXRecordDecl that that type refers to. - /// - /// If this is not a pointer or reference, or the type being pointed to does - /// not refer to a CXXRecordDecl, returns NULL. - const CXXRecordDecl *getPointeeCXXRecordDecl() const; - - /// 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. - 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; - - /// Get the base element type of this type, potentially discarding type - /// qualifiers. This should never be used when type qualifiers - /// are meaningful. - const Type *getBaseElementTypeUnsafe() const; - - /// If this is an array type, return the element type of the array, - /// potentially with type qualifiers missing. - /// This should never be used when type qualifiers are meaningful. - const Type *getArrayElementTypeNoTypeQual() const; - - /// If this is a pointer, ObjC object pointer, or block - /// pointer, this returns the respective pointee. - QualType getPointeeType() const; - - /// Return the specified type with any "sugar" removed from the type, - /// removing any typedefs, typeofs, etc., as well as any qualifiers. - const Type *getUnqualifiedDesugaredType() const; - - /// More type predicates useful for type checking/promotion - bool isPromotableIntegerType() const; // C99 6.3.1.1p2 - - /// Return true if this is an integer type that is - /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], - /// or an enum decl which has a signed representation. - bool isSignedIntegerType() const; - - /// Return true if this is an integer type that is - /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], - /// or an enum decl which has an unsigned representation. - bool isUnsignedIntegerType() const; - - /// Determines whether this is an integer type that is signed or an - /// enumeration types whose underlying type is a signed integer type. - bool isSignedIntegerOrEnumerationType() const; - - /// Determines whether this is an integer type that is unsigned or an - /// enumeration types whose underlying type is a unsigned integer type. - bool isUnsignedIntegerOrEnumerationType() const; - - /// Return true if this is not a variable sized type, - /// according to the rules of C99 6.7.5p3. It is not legal to call this on - /// incomplete types. - bool isConstantSizeType() const; - - /// Returns true if this type can be represented by some - /// set of type specifiers. - bool isSpecifierType() const; - - /// Determine the linkage of this type. - Linkage getLinkage() const; - - /// Determine the visibility of this type. - Visibility getVisibility() const { - return getLinkageAndVisibility().getVisibility(); - } - - /// Return true if the visibility was explicitly set is the code. - bool isVisibilityExplicit() const { - return getLinkageAndVisibility().isVisibilityExplicit(); - } - - /// Determine the linkage and visibility of this type. - LinkageInfo getLinkageAndVisibility() const; - - /// True if the computed linkage is valid. Used for consistency - /// checking. Should always return true. - bool isLinkageValid() const; - - /// Determine the nullability of the given type. - /// - /// Note that nullability is only captured as sugar within the type - /// system, not as part of the canonical type, so nullability will - /// be lost by canonicalization and desugaring. - Optional<NullabilityKind> getNullability(const ASTContext &context) const; - - /// Determine whether the given type can have a nullability - /// specifier applied to it, i.e., if it is any kind of pointer type - /// or a dependent type that could instantiate to any kind of - /// pointer type. - bool canHaveNullability() const; - - /// Retrieve the set of substitutions required when accessing a member - /// of the Objective-C receiver type that is declared in the given context. - /// - /// \c *this is the type of the object we're operating on, e.g., the - /// receiver for a message send or the base of a property access, and is - /// expected to be of some object or object pointer type. - /// - /// \param dc The declaration context for which we are building up a - /// substitution mapping, which should be an Objective-C class, extension, - /// category, or method within. - /// - /// \returns an array of type arguments that can be substituted for - /// the type parameters of the given declaration context in any type described - /// within that context, or an empty optional to indicate that no - /// substitution is required. - Optional<ArrayRef<QualType>> - getObjCSubstitutions(const DeclContext *dc) const; - - /// Determines if this is an ObjC interface type that may accept type - /// parameters. - bool acceptsObjCTypeParams() const; - - const char *getTypeClassName() const; - - QualType getCanonicalTypeInternal() const { - return CanonicalType; - } - CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h - void dump() const; - - friend class ASTReader; - friend class ASTWriter; -}; - -/// \brief This will check for a TypedefType by removing any existing sugar -/// until it reaches a TypedefType or a non-sugared type. -template <> const TypedefType *Type::getAs() const; - -/// \brief This will check for a TemplateSpecializationType by removing any -/// existing sugar until it reaches a TemplateSpecializationType or a -/// non-sugared type. -template <> const TemplateSpecializationType *Type::getAs() const; - -/// \brief This will check for an AttributedType by removing any existing sugar -/// until it reaches an AttributedType or a non-sugared type. -template <> const AttributedType *Type::getAs() const; - -// We can do canonical leaf types faster, because we don't have to -// worry about preserving child type decoration. -#define TYPE(Class, Base) -#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" - - -/// This class is used for builtin types like 'int'. Builtin -/// types are always canonical and have a literal name field. -class BuiltinType : public Type { -public: - enum Kind { -#define BUILTIN_TYPE(Id, SingletonId) Id, -#define LAST_BUILTIN_TYPE(Id) LastKind = Id -#include "clang/AST/BuiltinTypes.def" - }; - -public: - BuiltinType(Kind K) - : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), - /*InstantiationDependent=*/(K == Dependent), - /*VariablyModified=*/false, - /*Unexpanded paramter pack=*/false) { - BuiltinTypeBits.Kind = K; - } - - Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } - StringRef getName(const PrintingPolicy &Policy) const; - const char *getNameAsCString(const PrintingPolicy &Policy) const { - // The StringRef is null-terminated. - StringRef str = getName(Policy); - assert(!str.empty() && str.data()[str.size()] == '\0'); - return str.data(); - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - bool isInteger() const { - return getKind() >= Bool && getKind() <= Int128; - } - - bool isSignedInteger() const { - return getKind() >= Char_S && getKind() <= Int128; - } - - bool isUnsignedInteger() const { - return getKind() >= Bool && getKind() <= UInt128; - } - - bool isFloatingPoint() const { - return getKind() >= Half && getKind() <= LongDouble; - } - - /// Determines whether the given kind corresponds to a placeholder type. - static bool isPlaceholderTypeKind(Kind K) { - return K >= Overload; - } - - /// Determines whether this type is a placeholder type, i.e. a type - /// which cannot appear in arbitrary positions in a fully-formed - /// expression. - bool isPlaceholderType() const { - return isPlaceholderTypeKind(getKind()); - } - - /// Determines whether this type is a placeholder type other than - /// Overload. Most placeholder types require only syntactic - /// information about their context in order to be resolved (e.g. - /// whether it is a call expression), which means they can (and - /// should) be resolved in an earlier "phase" of analysis. - /// Overload expressions sometimes pick up further information - /// from their context, like whether the context expects a - /// specific function-pointer type, and so frequently need - /// special treatment. - bool isNonOverloadPlaceholderType() const { - return getKind() > Overload; - } - - static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } -}; - -/// Complex values, per C99 6.2.5p11. This supports the C99 complex -/// types (_Complex float etc) as well as the GCC integer complex extensions. -/// -class ComplexType : public Type, public llvm::FoldingSetNode { - QualType ElementType; - ComplexType(QualType Element, QualType CanonicalPtr) : - Type(Complex, CanonicalPtr, Element->isDependentType(), - Element->isInstantiationDependentType(), - Element->isVariablyModifiedType(), - Element->containsUnexpandedParameterPack()), - ElementType(Element) { - } - friend class ASTContext; // ASTContext creates these. - -public: - QualType getElementType() const { return ElementType; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) { - ID.AddPointer(Element.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { return T->getTypeClass() == Complex; } -}; - -/// 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->isInstantiationDependentType(), - 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; } -}; - -/// 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(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. - -public: - - QualType getPointeeType() const { return PointeeType; } - - /// Returns true if address spaces of pointers overlap. - /// OpenCL v2.0 defines conversion rules for pointers to different - /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping - /// address spaces. - /// CL1.1 or CL1.2: - /// address spaces overlap iff they are they same. - /// CL2.0 adds: - /// __generic overlaps with any address space except for __constant. - bool isAddressSpaceOverlapping(const PointerType &other) const { - Qualifiers thisQuals = PointeeType.getQualifiers(); - Qualifiers otherQuals = other.getPointeeType().getQualifiers(); - // Address spaces overlap if at least one of them is a superset of another - return thisQuals.isAddressSpaceSupersetOf(otherQuals) || - otherQuals.isAddressSpaceSupersetOf(thisQuals); - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { - ID.AddPointer(Pointee.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } -}; - -/// Represents a type which was implicitly adjusted by the semantic -/// engine for arbitrary reasons. For example, array and function types can -/// decay, and function types can have their calling conventions adjusted. -class AdjustedType : public Type, public llvm::FoldingSetNode { - QualType OriginalTy; - QualType AdjustedTy; - -protected: - AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, - QualType CanonicalPtr) - : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), - OriginalTy->isInstantiationDependentType(), - OriginalTy->isVariablyModifiedType(), - OriginalTy->containsUnexpandedParameterPack()), - OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} - - friend class ASTContext; // ASTContext creates these. - -public: - QualType getOriginalType() const { return OriginalTy; } - QualType getAdjustedType() const { return AdjustedTy; } - - bool isSugared() const { return true; } - QualType desugar() const { return AdjustedTy; } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, OriginalTy, AdjustedTy); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) { - ID.AddPointer(Orig.getAsOpaquePtr()); - ID.AddPointer(New.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == Adjusted || T->getTypeClass() == Decayed; - } -}; - -/// Represents a pointer type decayed from an array or function type. -class DecayedType : public AdjustedType { - - DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr) - : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) { - assert(isa<PointerType>(getAdjustedType())); - } - - friend class ASTContext; // ASTContext creates these. - -public: - QualType getDecayedType() const { return getAdjustedType(); } - - QualType getPointeeType() const { - return cast<PointerType>(getDecayedType())->getPointeeType(); - } - - static bool classof(const Type *T) { return T->getTypeClass() == Decayed; } -}; - -/// Pointer to a block type. -/// This type is to represent types syntactically represented as -/// "void (^)(int)", etc. Pointee is required to always be a function type. -/// -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(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. - -public: - - // Get the pointee type. Pointee is required to always be a function type. - QualType getPointeeType() const { return PointeeType; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { - ID.AddPointer(Pointee.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == BlockPointer; - } -}; - -/// Base for LValueReferenceType and RValueReferenceType -/// -class ReferenceType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; - -protected: - ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - Type(tc, CanonicalRef, Referencee->isDependentType(), - Referencee->isInstantiationDependentType(), - Referencee->isVariablyModifiedType(), - Referencee->containsUnexpandedParameterPack()), - PointeeType(Referencee) - { - ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; - ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); - } - -public: - 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->isInnerRef()) - T = T->PointeeType->castAs<ReferenceType>(); - return T->PointeeType; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, PointeeType, isSpelledAsLValue()); - } - static void Profile(llvm::FoldingSetNodeID &ID, - QualType Referencee, - bool SpelledAsLValue) { - ID.AddPointer(Referencee.getAsOpaquePtr()); - ID.AddBoolean(SpelledAsLValue); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == LValueReference || - T->getTypeClass() == RValueReference; - } -}; - -/// An lvalue reference type, per C++11 [dcl.ref]. -/// -class LValueReferenceType : public ReferenceType { - LValueReferenceType(QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) - {} - friend class ASTContext; // ASTContext creates these -public: - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == LValueReference; - } -}; - -/// An rvalue reference type, per C++11 [dcl.ref]. -/// -class RValueReferenceType : public ReferenceType { - RValueReferenceType(QualType Referencee, QualType CanonicalRef) : - ReferenceType(RValueReference, Referencee, CanonicalRef, false) { - } - friend class ASTContext; // ASTContext creates these -public: - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == RValueReference; - } -}; - -/// A pointer to member type per C++ 8.3.3 - Pointers to members. -/// -/// This includes both pointers to data members and pointer to member functions. -/// -class MemberPointerType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; - /// The class of which the pointee is a member. Must ultimately be a - /// RecordType, but could be a typedef or a template parameter too. - const Type *Class; - - MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : - Type(MemberPointer, CanonicalPtr, - Cls->isDependentType() || Pointee->isDependentType(), - (Cls->isInstantiationDependentType() || - Pointee->isInstantiationDependentType()), - Pointee->isVariablyModifiedType(), - (Cls->containsUnexpandedParameterPack() || - Pointee->containsUnexpandedParameterPack())), - PointeeType(Pointee), Class(Cls) { - } - friend class ASTContext; // ASTContext creates these. - -public: - QualType getPointeeType() const { return PointeeType; } - - /// Returns true if the member type (i.e. the pointee type) is a - /// function type rather than a data-member type. - bool isMemberFunctionPointer() const { - return PointeeType->isFunctionProtoType(); - } - - /// Returns true if the member type (i.e. the pointee type) is a - /// data type rather than a function type. - bool isMemberDataPointer() const { - return !PointeeType->isFunctionProtoType(); - } - - const Type *getClass() const { return Class; } - CXXRecordDecl *getMostRecentCXXRecordDecl() const; - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType(), getClass()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, - const Type *Class) { - ID.AddPointer(Pointee.getAsOpaquePtr()); - ID.AddPointer(Class); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == MemberPointer; - } -}; - -/// Represents an array type, per C99 6.7.5.2 - Array Declarators. -/// -class ArrayType : public Type, public llvm::FoldingSetNode { -public: - /// Capture whether this is a normal array (e.g. int X[4]) - /// an array with a static size (e.g. int X[static 4]), or an array - /// with a star size (e.g. int X[*]). - /// 'static' is only allowed on function parameters. - enum ArraySizeModifier { - Normal, Static, Star - }; -private: - /// The element type of the array. - QualType ElementType; - -protected: - // C++ [temp.dep.type]p1: - // A type is dependent if it is... - // - an array type constructed from any dependent type or whose - // size is specified by a constant expression that is - // value-dependent, - ArrayType(TypeClass tc, QualType et, QualType can, - ArraySizeModifier sm, unsigned tq, - bool ContainsUnexpandedParameterPack) - : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, - et->isInstantiationDependentType() || tc == DependentSizedArray, - (tc == VariableArray || et->isVariablyModifiedType()), - ContainsUnexpandedParameterPack), - ElementType(et) { - ArrayTypeBits.IndexTypeQuals = tq; - ArrayTypeBits.SizeModifier = sm; - } - - friend class ASTContext; // ASTContext creates these. - -public: - QualType getElementType() const { return ElementType; } - ArraySizeModifier getSizeModifier() const { - return ArraySizeModifier(ArrayTypeBits.SizeModifier); - } - Qualifiers getIndexTypeQualifiers() const { - return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers()); - } - unsigned getIndexTypeCVRQualifiers() const { - return ArrayTypeBits.IndexTypeQuals; - } - - static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray || - T->getTypeClass() == VariableArray || - T->getTypeClass() == IncompleteArray || - T->getTypeClass() == DependentSizedArray; - } -}; - -/// Represents the canonical version of C arrays with a specified constant size. -/// For example, the canonical type for 'int A[4 + 4*100]' is a -/// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType : public ArrayType { - llvm::APInt Size; // Allows us to unique the type. - - ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, - ArraySizeModifier sm, unsigned 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, et->containsUnexpandedParameterPack()), - Size(size) {} - friend class ASTContext; // ASTContext creates these. -public: - const llvm::APInt &getSize() const { return Size; } - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - - /// \brief Determine the number of bits required to address a member of - // an array with the given element type and number of elements. - static unsigned getNumAddressingBits(ASTContext &Context, - QualType ElementType, - const llvm::APInt &NumElements); - - /// \brief Determine the maximum number of active bits that an array's size - /// can require, which limits the maximum size of the array. - static unsigned getMaxSizeBits(ASTContext &Context); - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getSize(), - getSizeModifier(), getIndexTypeCVRQualifiers()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, - const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, - unsigned TypeQuals) { - ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(ArraySize.getZExtValue()); - ID.AddInteger(SizeMod); - ID.AddInteger(TypeQuals); - } - static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray; - } -}; - -/// Represents a C array with an unspecified size. For example 'int A[]' has -/// an IncompleteArrayType where the element type is 'int' and the size is -/// unspecified. -class IncompleteArrayType : public ArrayType { - - IncompleteArrayType(QualType et, QualType can, - ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()) {} - friend class ASTContext; // ASTContext creates these. -public: - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == IncompleteArray; - } - - friend class StmtIteratorBase; - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getSizeModifier(), - getIndexTypeCVRQualifiers()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, - ArraySizeModifier SizeMod, unsigned TypeQuals) { - ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(SizeMod); - ID.AddInteger(TypeQuals); - } -}; - -/// Represents a C array with a specified size that is not an -/// integer-constant-expression. For example, 'int s[x+foo()]'. -/// Since the size expression is an arbitrary expression, we store it as such. -/// -/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and -/// should not be: two lexically equivalent variable array types could mean -/// different things, for example, these variables do not have the same type -/// dynamically: -/// -/// void foo(int x) { -/// int Y[x]; -/// ++x; -/// int Z[x]; -/// } -/// -class VariableArrayType : public ArrayType { - /// An assignment-expression. VLA's are only permitted within - /// a function block. - Stmt *SizeExpr; - /// The range spanned by the left and right array brackets. - SourceRange Brackets; - - VariableArrayType(QualType et, QualType can, Expr *e, - ArraySizeModifier sm, unsigned tq, - SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - SizeExpr((Stmt*) e), Brackets(brackets) {} - friend class ASTContext; // ASTContext creates these. - -public: - Expr *getSizeExpr() const { - // We use C-style casts instead of cast<> here because we do not wish - // to have a dependency of Type.h on Stmt.h/Expr.h. - return (Expr*) SizeExpr; - } - SourceRange getBracketsRange() const { return Brackets; } - SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } - SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == VariableArray; - } - - friend class StmtIteratorBase; - - void Profile(llvm::FoldingSetNodeID &ID) { - llvm_unreachable("Cannot unique VariableArrayTypes."); - } -}; - -/// Represents an array type in C++ whose size is a value-dependent expression. -/// -/// For example: -/// \code -/// template<typename T, int Size> -/// class array { -/// T data[Size]; -/// }; -/// \endcode -/// -/// For these types, we won't actually know what the array bound is -/// until template instantiation occurs, at which point this will -/// become either a ConstantArrayType or a VariableArrayType. -class DependentSizedArrayType : public ArrayType { - const ASTContext &Context; - - /// \brief An assignment expression that will instantiate to the - /// size of the array. - /// - /// The expression itself might be null, in which case the array - /// type will have its size deduced from an initializer. - Stmt *SizeExpr; - - /// The range spanned by the left and right array brackets. - SourceRange Brackets; - - DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can, - Expr *e, ArraySizeModifier sm, unsigned tq, - SourceRange brackets); - - friend class ASTContext; // ASTContext creates these. - -public: - Expr *getSizeExpr() const { - // We use C-style casts instead of cast<> here because we do not wish - // to have a dependency of Type.h on Stmt.h/Expr.h. - return (Expr*) SizeExpr; - } - SourceRange getBracketsRange() const { return Brackets; } - SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } - SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == DependentSizedArray; - } - - friend class StmtIteratorBase; - - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getElementType(), - getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - QualType ET, ArraySizeModifier SizeMod, - unsigned TypeQuals, Expr *E); -}; - -/// Represents an extended vector type where either the type or size is -/// dependent. -/// -/// For example: -/// \code -/// template<typename T, int Size> -/// class vector { -/// typedef T __attribute__((ext_vector_type(Size))) type; -/// } -/// \endcode -class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { - const ASTContext &Context; - Expr *SizeExpr; - /// The element type of the array. - QualType ElementType; - SourceLocation loc; - - DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, - QualType can, Expr *SizeExpr, SourceLocation loc); - - friend class ASTContext; - -public: - Expr *getSizeExpr() const { return SizeExpr; } - QualType getElementType() const { return ElementType; } - SourceLocation getAttributeLoc() const { return loc; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == DependentSizedExtVector; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getElementType(), getSizeExpr()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - QualType ElementType, Expr *SizeExpr); -}; - - -/// Represents a GCC generic vector type. This type is created using -/// __attribute__((vector_size(n)), where "n" specifies the vector size in -/// bytes; or from an Altivec __vector or vector declaration. -/// Since the constructor takes the number of vector elements, the -/// client is responsible for converting the size into the number of elements. -class VectorType : public Type, public llvm::FoldingSetNode { -public: - 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: - /// The element type of the vector. - QualType ElementType; - - VectorType(QualType vecType, unsigned nElements, QualType canonType, - VectorKind vecKind); - - VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType, VectorKind vecKind); - - friend class ASTContext; // ASTContext creates these. - -public: - - QualType getElementType() const { return ElementType; } - unsigned getNumElements() const { return VectorTypeBits.NumElements; } - static bool isVectorSizeTooLarge(unsigned NumElements) { - return NumElements > VectorTypeBitfields::MaxNumElements; - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - VectorKind getVectorKind() const { - return VectorKind(VectorTypeBits.VecKind); - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getNumElements(), - getTypeClass(), getVectorKind()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, - unsigned NumElements, TypeClass TypeClass, - VectorKind VecKind) { - ID.AddPointer(ElementType.getAsOpaquePtr()); - ID.AddInteger(NumElements); - ID.AddInteger(TypeClass); - ID.AddInteger(VecKind); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; - } -}; - -/// ExtVectorType - Extended vector type. This type is created using -/// __attribute__((ext_vector_type(n)), where "n" is the number of elements. -/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This -/// class enables syntactic extensions, like Vector Components for accessing -/// 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, GenericVector) {} - friend class ASTContext; // ASTContext creates these. -public: - static int getPointAccessorIdx(char c) { - switch (c) { - default: return -1; - case 'x': return 0; - case 'y': return 1; - case 'z': return 2; - case 'w': return 3; - } - } - static int getNumericAccessorIdx(char c) { - switch (c) { - default: return -1; - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'A': - case 'a': return 10; - case 'B': - case 'b': return 11; - case 'C': - case 'c': return 12; - case 'D': - case 'd': return 13; - case 'E': - case 'e': return 14; - case 'F': - case 'f': return 15; - } - } - - static int getAccessorIdx(char c) { - if (int idx = getPointAccessorIdx(c)+1) return idx-1; - return getNumericAccessorIdx(c); - } - - bool isAccessorWithinNumElements(char c) const { - if (int idx = getAccessorIdx(c)+1) - return unsigned(idx-1) < getNumElements(); - return false; - } - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == ExtVector; - } -}; - -/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base -/// class of FunctionNoProtoType and FunctionProtoType. -/// -class FunctionType : public Type { - // The type returned by the function. - QualType ResultType; - - public: - /// 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. - // * ASTContext::getFooType - // * ASTContext::mergeFunctionTypes - // * FunctionNoProtoType::Profile - // * FunctionProtoType::Profile - // * TypePrinter::PrintFunctionProto - // * AST read and write - // * Codegen - class ExtInfo { - // Feel free to rearrange or add bits, but if you go over 9, - // you'll need to adjust both the Bits field below and - // Type::FunctionTypeBitfields. - - // | CC |noreturn|produces|regparm| - // |0 .. 3| 4 | 5 | 6 .. 8| - // - // regparm is either 0 (no regparm attribute) or the regparm value+1. - enum { CallConvMask = 0xF }; - enum { NoReturnMask = 0x10 }; - enum { ProducesResultMask = 0x20 }; - enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask), - RegParmOffset = 6 }; // Assumed to be the last field - - uint16_t Bits; - - ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(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, bool hasRegParm, unsigned regParm, CallingConv cc, - bool producesResult) { - assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); - Bits = ((unsigned) cc) | - (noReturn ? NoReturnMask : 0) | - (producesResult ? ProducesResultMask : 0) | - (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0); - } - - // Constructor with all defaults. Use when for example creating a - // function known to use defaults. - ExtInfo() : Bits(CC_C) { } - - // Constructor with just the calling convention, which is an important part - // of the canonical type. - ExtInfo(CallingConv CC) : Bits(CC) { } - - bool getNoReturn() const { return Bits & NoReturnMask; } - bool getProducesResult() const { return Bits & ProducesResultMask; } - bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } - unsigned getRegParm() const { - unsigned RegParm = Bits >> RegParmOffset; - if (RegParm > 0) - --RegParm; - return RegParm; - } - CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } - - bool operator==(ExtInfo Other) const { - return Bits == Other.Bits; - } - 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 { - if (noReturn) - return ExtInfo(Bits | NoReturnMask); - else - return ExtInfo(Bits & ~NoReturnMask); - } - - ExtInfo withProducesResult(bool producesResult) const { - if (producesResult) - return ExtInfo(Bits | ProducesResultMask); - else - return ExtInfo(Bits & ~ProducesResultMask); - } - - ExtInfo withRegParm(unsigned RegParm) const { - assert(RegParm < 7 && "Invalid regparm value"); - return ExtInfo((Bits & ~RegParmMask) | - ((RegParm + 1) << RegParmOffset)); - } - - ExtInfo withCallingConv(CallingConv cc) const { - return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc); - } - - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddInteger(Bits); - } - }; - -protected: - FunctionType(TypeClass tc, QualType res, - QualType Canonical, bool Dependent, - bool InstantiationDependent, - bool VariablyModified, bool ContainsUnexpandedParameterPack, - ExtInfo Info) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack), - ResultType(res) { - FunctionTypeBits.ExtInfo = Info.Bits; - } - unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } - -public: - QualType getReturnType() const { return ResultType; } - - bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } - unsigned getRegParmType() const { return getExtInfo().getRegParm(); } - /// Determine whether this function type includes the GNU noreturn - /// attribute. The C++11 [[noreturn]] attribute does not affect the function - /// type. - bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } - CallingConv getCallConv() const { return getExtInfo().getCC(); } - ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } - bool isConst() const { return getTypeQuals() & Qualifiers::Const; } - bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; } - bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; } - - /// \brief Determine the type of an expression that calls a function of - /// this type. - QualType getCallResultType(ASTContext &Context) const { - return getReturnType().getNonLValueExprType(Context); - } - - static StringRef getNameForCallConv(CallingConv CC); - - static bool classof(const Type *T) { - return T->getTypeClass() == FunctionNoProto || - T->getTypeClass() == FunctionProto; - } -}; - -/// 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, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, Canonical, - /*Dependent=*/false, /*InstantiationDependent=*/false, - Result->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false, Info) {} - - friend class ASTContext; // ASTContext creates these. - -public: - // No additional state past what FunctionType provides. - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getReturnType(), getExtInfo()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, - ExtInfo Info) { - Info.Profile(ID); - ID.AddPointer(ResultType.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == FunctionNoProto; - } -}; - -/// Represents a prototype with parameter type info, e.g. -/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no -/// parameters, not as having a single void parameter. Such a type can have an -/// exception specification, but this specification is not part of the canonical -/// type. -class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { -public: - struct ExceptionSpecInfo { - ExceptionSpecInfo() - : Type(EST_None), NoexceptExpr(nullptr), - SourceDecl(nullptr), SourceTemplate(nullptr) {} - - ExceptionSpecInfo(ExceptionSpecificationType EST) - : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), - SourceTemplate(nullptr) {} - - /// The kind of exception specification this is. - ExceptionSpecificationType Type; - /// Explicitly-specified list of exception types. - ArrayRef<QualType> Exceptions; - /// Noexcept expression, if this is EST_ComputedNoexcept. - Expr *NoexceptExpr; - /// The function whose exception specification this is, for - /// EST_Unevaluated and EST_Uninstantiated. - FunctionDecl *SourceDecl; - /// The function template whose exception specification this is instantiated - /// from, for EST_Uninstantiated. - FunctionDecl *SourceTemplate; - }; - - /// Extra information about a function prototype. - struct ExtProtoInfo { - ExtProtoInfo() - : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ConsumedParameters(nullptr) {} - - ExtProtoInfo(CallingConv CC) - : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ConsumedParameters(nullptr) {} - - ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { - ExtProtoInfo Result(*this); - Result.ExceptionSpec = O; - return Result; - } - - FunctionType::ExtInfo ExtInfo; - bool Variadic : 1; - bool HasTrailingReturn : 1; - unsigned char TypeQuals; - RefQualifierKind RefQualifier; - ExceptionSpecInfo ExceptionSpec; - const bool *ConsumedParameters; - }; - -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]->containsUnexpandedParameterPack()) - return true; - - return false; - } - - FunctionProtoType(QualType result, ArrayRef<QualType> params, - QualType canonical, const ExtProtoInfo &epi); - - /// The number of parameters this function has, not counting '...'. - unsigned NumParams : 15; - - /// The number of types in the exception spec, if any. - unsigned NumExceptions : 9; - - /// The type of exception specification this function has. - unsigned ExceptionSpecType : 4; - - /// Whether this function has any consumed parameters. - unsigned HasAnyConsumedParams : 1; - - /// Whether the function is variadic. - unsigned Variadic : 1; - - /// Whether this function has a trailing return type. - unsigned HasTrailingReturn : 1; - - // ParamInfo - There is an variable size array after the class in memory that - // holds the parameter types. - - // Exceptions - There is another variable size array after ArgInfo that - // holds the exception types. - - // NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing - // to the expression in the noexcept() specifier. - - // ExceptionSpecDecl, ExceptionSpecTemplate - Instead of Exceptions, there may - // be a pair of FunctionDecl* pointing to the function which should be used to - // instantiate this function type's exception specification, and the function - // from which it should be instantiated. - - // ConsumedParameters - A variable size array, following Exceptions - // and of length NumParams, holding flags indicating which parameters - // are consumed. This only appears if HasAnyConsumedParams is true. - - friend class ASTContext; // ASTContext creates these. - - const bool *getConsumedParamsBuffer() const { - assert(hasAnyConsumedParams()); - - // Find the end of the exceptions. - Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end()); - if (getExceptionSpecType() == EST_ComputedNoexcept) - eh_end += 1; // NoexceptExpr - // The memory layout of these types isn't handled here, so - // hopefully this is never called for them? - assert(getExceptionSpecType() != EST_Uninstantiated && - getExceptionSpecType() != EST_Unevaluated); - - return reinterpret_cast<const bool*>(eh_end); - } - -public: - unsigned getNumParams() const { return NumParams; } - QualType getParamType(unsigned i) const { - assert(i < NumParams && "invalid parameter index"); - return param_type_begin()[i]; - } - ArrayRef<QualType> getParamTypes() const { - return llvm::makeArrayRef(param_type_begin(), param_type_end()); - } - - ExtProtoInfo getExtProtoInfo() const { - ExtProtoInfo EPI; - EPI.ExtInfo = getExtInfo(); - EPI.Variadic = isVariadic(); - EPI.HasTrailingReturn = hasTrailingReturn(); - EPI.ExceptionSpec.Type = getExceptionSpecType(); - EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); - EPI.RefQualifier = getRefQualifier(); - if (EPI.ExceptionSpec.Type == EST_Dynamic) { - EPI.ExceptionSpec.Exceptions = exceptions(); - } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { - EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); - } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { - EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); - EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate(); - } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { - EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); - } - if (hasAnyConsumedParams()) - EPI.ConsumedParameters = getConsumedParamsBuffer(); - return EPI; - } - - /// Get the kind of exception specification on this function. - ExceptionSpecificationType getExceptionSpecType() const { - return static_cast<ExceptionSpecificationType>(ExceptionSpecType); - } - /// Return whether this function has any kind of exception spec. - bool hasExceptionSpec() const { - return getExceptionSpecType() != EST_None; - } - /// Return whether this function has a dynamic (throw) exception spec. - bool hasDynamicExceptionSpec() const { - return isDynamicExceptionSpec(getExceptionSpecType()); - } - /// Return whether this function has a noexcept exception spec. - bool hasNoexceptExceptionSpec() const { - return isNoexceptExceptionSpec(getExceptionSpecType()); - } - /// Return whether this function has a dependent exception spec. - bool hasDependentExceptionSpec() const; - /// Result type of getNoexceptSpec(). - enum NoexceptResult { - NR_NoNoexcept, ///< There is no noexcept specifier. - NR_BadNoexcept, ///< The noexcept specifier has a bad expression. - NR_Dependent, ///< The noexcept specifier is dependent. - NR_Throw, ///< The noexcept specifier evaluates to false. - NR_Nothrow ///< The noexcept specifier evaluates to true. - }; - /// Get the meaning of the noexcept spec on this function, if any. - NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const; - unsigned getNumExceptions() const { return NumExceptions; } - QualType getExceptionType(unsigned i) const { - assert(i < NumExceptions && "Invalid exception number!"); - return exception_begin()[i]; - } - Expr *getNoexceptExpr() const { - if (getExceptionSpecType() != EST_ComputedNoexcept) - return nullptr; - // NoexceptExpr sits where the arguments end. - return *reinterpret_cast<Expr *const *>(param_type_end()); - } - /// \brief If this function type has an exception specification which hasn't - /// been determined yet (either because it has not been evaluated or because - /// it has not been instantiated), this is the function whose exception - /// specification is represented by this type. - FunctionDecl *getExceptionSpecDecl() const { - if (getExceptionSpecType() != EST_Uninstantiated && - getExceptionSpecType() != EST_Unevaluated) - return nullptr; - return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; - } - /// \brief If this function type has an uninstantiated exception - /// specification, this is the function whose exception specification - /// should be instantiated to find the exception specification for - /// this type. - FunctionDecl *getExceptionSpecTemplate() const { - if (getExceptionSpecType() != EST_Uninstantiated) - return nullptr; - return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; - } - /// Determine whether this function type has a non-throwing exception - /// specification. If this depends on template arguments, returns - /// \c ResultIfDependent. - bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const; - - bool isVariadic() const { return Variadic; } - - /// 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. - bool isTemplateVariadic() const; - - bool hasTrailingReturn() const { return HasTrailingReturn; } - - unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } - - - /// Retrieve the ref-qualifier associated with this function type. - RefQualifierKind getRefQualifier() const { - return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); - } - - typedef const QualType *param_type_iterator; - typedef llvm::iterator_range<param_type_iterator> param_type_range; - - param_type_range param_types() const { - return param_type_range(param_type_begin(), param_type_end()); - } - param_type_iterator param_type_begin() const { - return reinterpret_cast<const QualType *>(this+1); - } - param_type_iterator param_type_end() const { - return param_type_begin() + NumParams; - } - - typedef const QualType *exception_iterator; - - ArrayRef<QualType> exceptions() const { - return llvm::makeArrayRef(exception_begin(), exception_end()); - } - exception_iterator exception_begin() const { - // exceptions begin where arguments end - return param_type_end(); - } - exception_iterator exception_end() const { - if (getExceptionSpecType() != EST_Dynamic) - return exception_begin(); - return exception_begin() + NumExceptions; - } - - bool hasAnyConsumedParams() const { return HasAnyConsumedParams; } - bool isParamConsumed(unsigned I) const { - assert(I < getNumParams() && "parameter index out of range"); - if (hasAnyConsumedParams()) - return getConsumedParamsBuffer()[I]; - return false; - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void printExceptionSpecification(raw_ostream &OS, - const PrintingPolicy &Policy) const; - - static bool classof(const Type *T) { - return T->getTypeClass() == FunctionProto; - } - - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); - static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, - param_type_iterator ArgTys, unsigned NumArgs, - const ExtProtoInfo &EPI, const ASTContext &Context); -}; - -/// \brief Represents the dependent type named by a dependently-scoped -/// typename using declaration, e.g. -/// using typename Base<T>::foo; -/// -/// Template instantiation turns these into the underlying type. -class UnresolvedUsingType : public Type { - UnresolvedUsingTypenameDecl *Decl; - - UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, true, false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. -public: - - UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == UnresolvedUsing; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - return Profile(ID, Decl); - } - static void Profile(llvm::FoldingSetNodeID &ID, - UnresolvedUsingTypenameDecl *D) { - ID.AddPointer(D); - } -}; - - -class TypedefType : public Type { - TypedefNameDecl *Decl; -protected: - TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefNameDecl*>(D)) { - assert(!isa<TypedefType>(can) && "Invalid canonical type"); - } - friend class ASTContext; // ASTContext creates these. -public: - - TypedefNameDecl *getDecl() const { return Decl; } - - bool isSugared() const { return true; } - QualType desugar() const; - - static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } -}; - -/// Represents a `typeof` (or __typeof__) expression (a GCC extension). -class TypeOfExprType : public Type { - Expr *TOExpr; - -protected: - TypeOfExprType(Expr *E, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. -public: - Expr *getUnderlyingExpr() const { return TOExpr; } - - /// \brief Remove a single level of sugar. - QualType desugar() const; - - /// \brief Returns whether this type directly provides sugar. - bool isSugared() const; - - static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } -}; - -/// \brief Internal representation of canonical, dependent -/// `typeof(expr)` types. -/// -/// This class is used internally by the ASTContext to manage -/// canonical, dependent types, only. Clients will only see instances -/// of this class via TypeOfExprType nodes. -class DependentTypeOfExprType - : public TypeOfExprType, public llvm::FoldingSetNode { - const ASTContext &Context; - -public: - DependentTypeOfExprType(const ASTContext &Context, Expr *E) - : TypeOfExprType(E), Context(Context) { } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getUnderlyingExpr()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - Expr *E); -}; - -/// Represents `typeof(type)`, a GCC extension. -class TypeOfType : public Type { - QualType TOType; - TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), - T->isInstantiationDependentType(), - T->isVariablyModifiedType(), - T->containsUnexpandedParameterPack()), - TOType(T) { - assert(!isa<TypedefType>(can) && "Invalid canonical type"); - } - friend class ASTContext; // ASTContext creates these. -public: - QualType getUnderlyingType() const { return TOType; } - - /// \brief Remove a single level of sugar. - QualType desugar() const { return getUnderlyingType(); } - - /// \brief Returns whether this type directly provides sugar. - bool isSugared() const { return true; } - - static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } -}; - -/// Represents the type `decltype(expr)` (C++11). -class DecltypeType : public Type { - Expr *E; - QualType UnderlyingType; - -protected: - DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. -public: - Expr *getUnderlyingExpr() const { return E; } - QualType getUnderlyingType() const { return UnderlyingType; } - - /// \brief Remove a single level of sugar. - QualType desugar() const; - - /// \brief Returns whether this type directly provides sugar. - bool isSugared() const; - - static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } -}; - -/// \brief Internal representation of canonical, dependent -/// decltype(expr) types. -/// -/// This class is used internally by the ASTContext to manage -/// canonical, dependent types, only. Clients will only see instances -/// of this class via DecltypeType nodes. -class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { - const ASTContext &Context; - -public: - DependentDecltypeType(const ASTContext &Context, Expr *E); - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getUnderlyingExpr()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - Expr *E); -}; - -/// A unary type transform, which is a type constructed from another. -class UnaryTransformType : public Type { -public: - enum UTTKind { - EnumUnderlyingType - }; - -private: - /// The untransformed type. - QualType BaseType; - /// The transformed type if not dependent, otherwise the same as BaseType. - QualType UnderlyingType; - - UTTKind UKind; -protected: - UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind, - QualType CanonicalTy); - friend class ASTContext; -public: - bool isSugared() const { return !isDependentType(); } - QualType desugar() const { return UnderlyingType; } - - QualType getUnderlyingType() const { return UnderlyingType; } - QualType getBaseType() const { return BaseType; } - - UTTKind getUTTKind() const { return UKind; } - - static bool classof(const Type *T) { - return T->getTypeClass() == UnaryTransform; - } -}; - -class TagType : public Type { - /// Stores the TagDecl associated with this type. The decl may point to any - /// TagDecl that declares the entity. - TagDecl * decl; - - friend class ASTReader; - -protected: - TagType(TypeClass TC, const TagDecl *D, QualType can); - -public: - TagDecl *getDecl() const; - - /// Determines whether this type is in the process of being defined. - bool isBeingDefined() const; - - static bool classof(const Type *T) { - return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; - } -}; - -/// A helper class that allows the use of isa/cast/dyncast -/// to detect TagType objects of structs/unions/classes. -class RecordType : public TagType { -protected: - explicit RecordType(const RecordDecl *D) - : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { } - explicit RecordType(TypeClass TC, RecordDecl *D) - : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: - - RecordDecl *getDecl() const { - return reinterpret_cast<RecordDecl*>(TagType::getDecl()); - } - - // FIXME: This predicate is a helper to QualType/Type. It needs to - // recursively check all fields for const-ness. If any field is declared - // const, it needs to return false. - bool hasConstFields() const { return false; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { return T->getTypeClass() == Record; } -}; - -/// A helper class that allows the use of isa/cast/dyncast -/// to detect TagType objects of enums. -class EnumType : public TagType { - explicit EnumType(const EnumDecl *D) - : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: - - EnumDecl *getDecl() const { - return reinterpret_cast<EnumDecl*>(TagType::getDecl()); - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { return T->getTypeClass() == Enum; } -}; - -/// 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, - attr_objc_ownership, - attr_pcs, - attr_pcs_vfp, - - FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_pcs_vfp, - - // No operand. - attr_noreturn, - attr_cdecl, - attr_fastcall, - attr_stdcall, - attr_thiscall, - attr_pascal, - attr_vectorcall, - attr_inteloclbicc, - attr_ms_abi, - attr_sysv_abi, - attr_ptr32, - attr_ptr64, - attr_sptr, - attr_uptr, - attr_nonnull, - attr_nullable, - attr_null_unspecified, - attr_objc_kindof, - attr_objc_inert_unsafe_unretained, - }; - -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->isInstantiationDependentType(), - 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(); } - - /// Does this attribute behave like a type qualifier? - /// - /// A type qualifier adjusts a type to provide specialized rules for - /// a specific object, like the standard const and volatile qualifiers. - /// This includes attributes controlling things like nullability, - /// address spaces, and ARC ownership. The value of the object is still - /// largely described by the modified type. - /// - /// In contrast, many type attributes "rewrite" their modified type to - /// produce a fundamentally different type, not necessarily related in any - /// formalizable way to the original type. For example, calling convention - /// and vector attributes are not simple type qualifiers. - /// - /// Type qualifiers are often, but not always, reflected in the canonical - /// type. - bool isQualifier() const; - - bool isMSTypeSpec() const; - - bool isCallingConv() const; - - llvm::Optional<NullabilityKind> getImmediateNullability() const; - - /// Retrieve the attribute kind corresponding to the given - /// nullability kind. - static Kind getNullabilityAttrKind(NullabilityKind kind) { - switch (kind) { - case NullabilityKind::NonNull: - return attr_nonnull; - - case NullabilityKind::Nullable: - return attr_nullable; - - case NullabilityKind::Unspecified: - return attr_null_unspecified; - } - llvm_unreachable("Unknown nullability kind."); - } - - /// Strip off the top-level nullability annotation on the given - /// type, if it's there. - /// - /// \param T The type to strip. If the type is exactly an - /// AttributedType specifying nullability (without looking through - /// type sugar), the nullability is returned and this type changed - /// to the underlying modified type. - /// - /// \returns the top-level nullability, if present. - static Optional<NullabilityKind> stripOuterNullability(QualType &T); - - 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; - } -}; - -class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { - // Helper data collector for canonical types. - struct CanonicalTTPTInfo { - unsigned Depth : 15; - unsigned ParameterPack : 1; - unsigned Index : 16; - }; - - union { - // Info for the canonical type. - CanonicalTTPTInfo CanTTPTInfo; - // Info for the non-canonical type. - TemplateTypeParmDecl *TTPDecl; - }; - - /// Build a non-canonical type. - TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) - : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - Canon->containsUnexpandedParameterPack()), - TTPDecl(TTPDecl) { } - - /// Build the canonical type. - TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), - /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, PP) { - CanTTPTInfo.Depth = D; - CanTTPTInfo.Index = I; - CanTTPTInfo.ParameterPack = PP; - } - - friend class ASTContext; // ASTContext creates these - - const CanonicalTTPTInfo& getCanTTPTInfo() const { - QualType Can = getCanonicalTypeInternal(); - return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo; - } - -public: - unsigned getDepth() const { return getCanTTPTInfo().Depth; } - unsigned getIndex() const { return getCanTTPTInfo().Index; } - bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } - - TemplateTypeParmDecl *getDecl() const { - return isCanonicalUnqualified() ? nullptr : TTPDecl; - } - - IdentifierInfo *getIdentifier() const; - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, - unsigned Index, bool ParameterPack, - TemplateTypeParmDecl *TTPDecl) { - ID.AddInteger(Depth); - ID.AddInteger(Index); - ID.AddBoolean(ParameterPack); - ID.AddPointer(TTPDecl); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == TemplateTypeParm; - } -}; - -/// \brief Represents the result of substituting a type for a template -/// type parameter. -/// -/// Within an instantiated template, all template type parameters have -/// been replaced with these. They are used solely to record that a -/// type was originally written as a template type parameter; -/// therefore they are never canonical. -class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { - // The original type parameter. - const TemplateTypeParmType *Replaced; - - SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), - Canon->isInstantiationDependentType(), - Canon->isVariablyModifiedType(), - Canon->containsUnexpandedParameterPack()), - Replaced(Param) { } - - friend class ASTContext; - -public: - /// Gets the template parameter that was substituted for. - const TemplateTypeParmType *getReplacedParameter() const { - return Replaced; - } - - /// Gets the type that was substituted for the template - /// parameter. - QualType getReplacementType() const { - return getCanonicalTypeInternal(); - } - - bool isSugared() const { return true; } - QualType desugar() const { return getReplacementType(); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getReplacedParameter(), getReplacementType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, - QualType Replacement) { - ID.AddPointer(Replaced); - ID.AddPointer(Replacement.getAsOpaquePtr()); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == SubstTemplateTypeParm; - } -}; - -/// \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 *getIdentifier() const { return Replaced->getIdentifier(); } - - /// 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; - } -}; - -/// \brief Represents a C++11 auto or C++14 decltype(auto) type. -/// -/// These types are usually a placeholder for a deduced type. However, before -/// the initializer is attached, or if the initializer is type-dependent, there -/// is no deduced type and an auto type is canonical. In the latter case, it is -/// also a dependent type. -class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) - : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, - /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, - /*VariablyModified=*/false, - /*ContainsParameterPack=*/DeducedType.isNull() - ? false : DeducedType->containsUnexpandedParameterPack()) { - assert((DeducedType.isNull() || !IsDependent) && - "auto deduced to dependent type"); - AutoTypeBits.Keyword = (unsigned)Keyword; - } - - friend class ASTContext; // ASTContext creates these - -public: - bool isDecltypeAuto() const { - return getKeyword() == AutoTypeKeyword::DecltypeAuto; - } - AutoTypeKeyword getKeyword() const { - return (AutoTypeKeyword)AutoTypeBits.Keyword; - } - - bool isSugared() const { return !isCanonicalUnqualified(); } - QualType desugar() const { return getCanonicalTypeInternal(); } - - /// \brief Get the type deduced for this auto type, or null if it's either - /// not been deduced or was deduced to a dependent type. - QualType getDeducedType() const { - return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); - } - bool isDeduced() const { - return !isCanonicalUnqualified() || isDependentType(); - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType(), getKeyword(), isDependentType()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, - AutoTypeKeyword Keyword, bool IsDependent) { - ID.AddPointer(Deduced.getAsOpaquePtr()); - ID.AddInteger((unsigned)Keyword); - ID.AddBoolean(IsDependent); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == Auto; - } -}; - -/// \brief Represents a type template specialization; the template -/// must be a class template, a type alias template, or a template -/// template parameter. A template which cannot be resolved to one of -/// these, e.g. because it is written with a dependent scope -/// specifier, is instead represented as a -/// @c DependentTemplateSpecializationType. -/// -/// A non-dependent template specialization type is always "sugar", -/// typically for a \c RecordType. For example, a class template -/// specialization type of \c vector<int> will refer to a tag type for -/// the instantiation \c std::vector<int, std::allocator<int>> -/// -/// Template specializations are dependent if either the template or -/// any of the template arguments are dependent, in which case the -/// type may also be canonical. -/// -/// Instances of this type are allocated with a trailing array of -/// TemplateArguments, followed by a QualType representing the -/// non-canonical aliased type when the template is a type alias -/// template. -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType - : public Type, - public llvm::FoldingSetNode { - /// The name of the template being specialized. This is - /// either a TemplateName::Template (in which case it is a - /// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a - /// TypeAliasTemplateDecl*), a - /// TemplateName::SubstTemplateTemplateParmPack, or a - /// TemplateName::SubstTemplateTemplateParm (in which case the - /// replacement must, recursively, be one of these). - TemplateName Template; - - /// The number of template arguments named in this class template - /// specialization. - unsigned NumArgs : 31; - - /// Whether this template specialization type is a substituted type alias. - bool TypeAlias : 1; - - TemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, QualType Canon, - QualType Aliased); - - friend class ASTContext; // ASTContext creates these - -public: - /// Determine whether any of the given template arguments are dependent. - static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, - unsigned NumArgs, - bool &InstantiationDependent); - - static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, - bool &InstantiationDependent); - - /// \brief Print a template argument list, including the '<' and '>' - /// enclosing the template arguments. - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgument *Args, - unsigned NumArgs, - const PrintingPolicy &Policy, - bool SkipBrackets = false); - - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentLoc *Args, - unsigned NumArgs, - const PrintingPolicy &Policy); - - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &, - const PrintingPolicy &Policy); - - /// True if this template specialization type matches a current - /// instantiation in the context in which it is found. - bool isCurrentInstantiation() const { - return isa<InjectedClassNameType>(getCanonicalTypeInternal()); - } - - /// \brief Determine if this template specialization type is for a type alias - /// template that has been substituted. - /// - /// Nearly every template specialization type whose template is an alias - /// template will be substituted. However, this is not the case when - /// the specialization contains a pack expansion but the template alias - /// does not have a corresponding parameter pack, e.g., - /// - /// \code - /// template<typename T, typename U, typename V> struct S; - /// template<typename T, typename U> using A = S<T, int, U>; - /// template<typename... Ts> struct X { - /// typedef A<Ts...> type; // not a type alias - /// }; - /// \endcode - bool isTypeAlias() const { return TypeAlias; } - - /// Get the aliased type, if this is a specialization of a type alias - /// template. - QualType getAliasedType() const { - assert(isTypeAlias() && "not a type alias template specialization"); - return *reinterpret_cast<const QualType*>(end()); - } - - typedef const TemplateArgument * iterator; - - iterator begin() const { return getArgs(); } - iterator end() const; // defined inline in TemplateBase.h - - /// Retrieve the name of the template that we are specializing. - TemplateName getTemplateName() const { return Template; } - - /// Retrieve the template arguments. - const TemplateArgument *getArgs() const { - return reinterpret_cast<const TemplateArgument *>(this + 1); - } - - /// Retrieve the number of template arguments. - unsigned getNumArgs() const { return NumArgs; } - - /// Retrieve a specific template argument as a type. - /// \pre \c isArgType(Arg) - const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h - - bool isSugared() const { - return !isDependentType() || isCurrentInstantiation() || isTypeAlias(); - } - QualType desugar() const { return getCanonicalTypeInternal(); } - - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, Template, getArgs(), NumArgs, Ctx); - if (isTypeAlias()) - getAliasedType().Profile(ID); - } - - static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, - const ASTContext &Context); - - static bool classof(const Type *T) { - return T->getTypeClass() == TemplateSpecialization; - } -}; - -/// The injected class name of a C++ class template or class -/// template partial specialization. Used to record that a type was -/// spelled with a bare identifier rather than as a template-id; the -/// equivalent for non-templated classes is just RecordType. -/// -/// Injected class name types are always dependent. Template -/// instantiation turns these into RecordTypes. -/// -/// Injected class name types are always canonical. This works -/// because it is impossible to compare an injected class name type -/// with the corresponding non-injected template type, for the same -/// reason that it is impossible to directly compare template -/// parameters from different dependent contexts: injected class name -/// types can only occur within the scope of a particular templated -/// declaration, and within that scope every template specialization -/// will canonicalize to the injected class name (when appropriate -/// according to the rules of the language). -class InjectedClassNameType : public Type { - CXXRecordDecl *Decl; - - /// The template specialization which this type represents. - /// For example, in - /// template <class T> class A { ... }; - /// this is A<T>, whereas in - /// template <class X, class Y> class A<B<X,Y> > { ... }; - /// this is A<B<X,Y> >. - /// - /// It is always unqualified, always a template specialization type, - /// and always dependent. - QualType InjectedType; - - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not - // currently suitable for AST reading, too much - // interdependencies. - InjectedClassNameType(CXXRecordDecl *D, QualType TST) - : Type(InjectedClassName, QualType(), /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(D), InjectedType(TST) { - assert(isa<TemplateSpecializationType>(TST)); - assert(!TST.hasQualifiers()); - assert(TST->isDependentType()); - } - -public: - QualType getInjectedSpecializationType() const { return InjectedType; } - const TemplateSpecializationType *getInjectedTST() const { - return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); - } - - CXXRecordDecl *getDecl() const; - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == InjectedClassName; - } -}; - -/// \brief The kind of a tag type. -enum TagTypeKind { - /// \brief The "struct" keyword. - TTK_Struct, - /// \brief The "__interface" keyword. - TTK_Interface, - /// \brief The "union" keyword. - TTK_Union, - /// \brief The "class" keyword. - TTK_Class, - /// \brief The "enum" keyword. - TTK_Enum -}; - -/// \brief The elaboration keyword that precedes a qualified type name or -/// introduces an elaborated-type-specifier. -enum ElaboratedTypeKeyword { - /// \brief The "struct" keyword introduces the elaborated-type-specifier. - ETK_Struct, - /// \brief The "__interface" keyword introduces the elaborated-type-specifier. - ETK_Interface, - /// \brief The "union" keyword introduces the elaborated-type-specifier. - ETK_Union, - /// \brief The "class" keyword introduces the elaborated-type-specifier. - ETK_Class, - /// \brief The "enum" keyword introduces the elaborated-type-specifier. - ETK_Enum, - /// \brief The "typename" keyword precedes the qualified type name, e.g., - /// \c typename T::type. - ETK_Typename, - /// \brief No keyword precedes the qualified type name. - ETK_None -}; - -/// A helper class for Type nodes having an ElaboratedTypeKeyword. -/// The keyword in stored in the free bits of the base class. -/// Also provides a few static helpers for converting and printing -/// elaborated type keyword and tag type kind enumerations. -class TypeWithKeyword : public Type { -protected: - TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, - QualType Canonical, bool Dependent, - bool InstantiationDependent, bool VariablyModified, - bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack) { - TypeWithKeywordBits.Keyword = Keyword; - } - -public: - ElaboratedTypeKeyword getKeyword() const { - return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword); - } - - /// Converts a type specifier (DeclSpec::TST) into an elaborated type keyword. - static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec); - - /// Converts a type specifier (DeclSpec::TST) into a tag type kind. - /// It is an error to provide a type specifier which *isn't* a tag kind here. - static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec); - - /// Converts a TagTypeKind into an elaborated type keyword. - static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag); - - /// Converts an elaborated type keyword into a TagTypeKind. - /// It is an error to provide an elaborated type keyword - /// which *isn't* a tag kind here. - static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword); - - static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); - - static StringRef getKeywordName(ElaboratedTypeKeyword Keyword); - - static StringRef getTagTypeKindName(TagTypeKind Kind) { - return getKeywordName(getKeywordForTagTypeKind(Kind)); - } - - class CannotCastToThisType {}; - static CannotCastToThisType classof(const Type *); -}; - -/// \brief Represents a type that was referred to using an elaborated type -/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, -/// or both. -/// -/// This type is used to keep track of a type name as written in the -/// source code, including tag keywords and any nested-name-specifiers. -/// The type itself is always "sugar", used to express what was written -/// in the source code but containing no additional semantic information. -class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { - - /// The nested name specifier containing the qualifier. - NestedNameSpecifier *NNS; - - /// The type that this qualified name refers to. - QualType NamedType; - - ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - QualType NamedType, QualType CanonType) - : TypeWithKeyword(Keyword, Elaborated, CanonType, - NamedType->isDependentType(), - NamedType->isInstantiationDependentType(), - NamedType->isVariablyModifiedType(), - NamedType->containsUnexpandedParameterPack()), - NNS(NNS), NamedType(NamedType) { - assert(!(Keyword == ETK_None && NNS == nullptr) && - "ElaboratedType cannot have elaborated type keyword " - "and name qualifier both null."); - } - - friend class ASTContext; // ASTContext creates these - -public: - ~ElaboratedType(); - - /// Retrieve the qualification on this type. - NestedNameSpecifier *getQualifier() const { return NNS; } - - /// Retrieve the type named by the qualified-id. - QualType getNamedType() const { return NamedType; } - - /// Remove a single level of sugar. - QualType desugar() const { return getNamedType(); } - - /// Returns whether this type directly provides sugar. - bool isSugared() const { return true; } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getKeyword(), NNS, NamedType); - } - - static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType NamedType) { - ID.AddInteger(Keyword); - ID.AddPointer(NNS); - NamedType.Profile(ID); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == Elaborated; - } -}; - -/// \brief Represents a qualified type name for which the type name is -/// dependent. -/// -/// DependentNameType represents a class of dependent types that involve a -/// possibly dependent nested-name-specifier (e.g., "T::") followed by a -/// name of a type. The DependentNameType may start with a "typename" (for a -/// typename-specifier), "class", "struct", "union", or "enum" (for a -/// dependent elaborated-type-specifier), or nothing (in contexts where we -/// know that we must be referring to a type, e.g., in a base class specifier). -/// Typically the nested-name-specifier is dependent, but in MSVC compatibility -/// mode, this type is used with non-dependent names to delay name lookup until -/// instantiation. -class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { - - /// \brief The nested name specifier containing the qualifier. - NestedNameSpecifier *NNS; - - /// \brief The type that this typename specifier refers to. - const IdentifierInfo *Name; - - DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name) {} - - friend class ASTContext; // ASTContext creates these - -public: - /// Retrieve the qualification on this type. - NestedNameSpecifier *getQualifier() const { return NNS; } - - /// Retrieve the type named by the typename specifier as an identifier. - /// - /// This routine will return a non-NULL identifier pointer when the - /// form of the original typename was terminated by an identifier, - /// e.g., "typename T::type". - const IdentifierInfo *getIdentifier() const { - return Name; - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getKeyword(), NNS, Name); - } - - static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, const IdentifierInfo *Name) { - ID.AddInteger(Keyword); - ID.AddPointer(NNS); - ID.AddPointer(Name); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == DependentName; - } -}; - -/// Represents a template specialization type whose template cannot be -/// resolved, e.g. -/// A<T>::template B<T> -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType - : public TypeWithKeyword, - public llvm::FoldingSetNode { - - /// The nested name specifier containing the qualifier. - NestedNameSpecifier *NNS; - - /// The identifier of the template. - const IdentifierInfo *Name; - - /// \brief The number of template arguments named in this class template - /// specialization. - unsigned NumArgs; - - const TemplateArgument *getArgBuffer() const { - return reinterpret_cast<const TemplateArgument*>(this+1); - } - TemplateArgument *getArgBuffer() { - return reinterpret_cast<TemplateArgument*>(this+1); - } - - DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args, - QualType Canon); - - friend class ASTContext; // ASTContext creates these - -public: - NestedNameSpecifier *getQualifier() const { return NNS; } - const IdentifierInfo *getIdentifier() const { return Name; } - - /// \brief Retrieve the template arguments. - const TemplateArgument *getArgs() const { - return getArgBuffer(); - } - - /// \brief Retrieve the number of template arguments. - unsigned getNumArgs() const { return NumArgs; } - - const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h - - typedef const TemplateArgument * iterator; - iterator begin() const { return getArgs(); } - iterator end() const; // inline in TemplateBase.h - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, - ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *Qualifier, - const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args); - - static bool classof(const Type *T) { - return T->getTypeClass() == DependentTemplateSpecialization; - } -}; - -/// \brief Represents a pack expansion of types. -/// -/// Pack expansions are part of C++11 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, - Optional<unsigned> NumExpansions) - : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), - /*InstantiationDependent=*/true, - /*VariablyModified=*/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. - Optional<unsigned> getNumExpansions() const { - if (NumExpansions) - return NumExpansions - 1; - - return None; - } - - bool isSugared() const { return !Pattern->isDependentType(); } - QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPattern(), getNumExpansions()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern, - Optional<unsigned> NumExpansions) { - ID.AddPointer(Pattern.getAsOpaquePtr()); - ID.AddBoolean(NumExpansions.hasValue()); - if (NumExpansions) - ID.AddInteger(*NumExpansions); - } - - static bool classof(const Type *T) { - return T->getTypeClass() == PackExpansion; - } -}; - -/// Represents a class type in Objective C. -/// -/// Every Objective C type is a combination of a base type, a set of -/// type arguments (optional, for parameterized classes) and a list of -/// protocols. -/// -/// Given the following declarations: -/// \code -/// \@class C<T>; -/// \@protocol P; -/// \endcode -/// -/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType -/// with base C and no protocols. -/// -/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P]. -/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no -/// protocol list. -/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*', -/// and protocol list [P]. -/// -/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose -/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType -/// and no protocols. -/// -/// 'id<P>' is an ObjCObjectPointerType whose pointee is an ObjCObjectType -/// 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 { - // ObjCObjectType.NumTypeArgs - the number of type arguments stored - // after the ObjCObjectPointerType node. - // ObjCObjectType.NumProtocols - the number of protocols stored - // after the type arguments of 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; - - /// Cached superclass type. - mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool> - CachedSuperClassType; - - ObjCProtocolDecl * const *getProtocolStorage() const { - return const_cast<ObjCObjectType*>(this)->getProtocolStorage(); - } - - QualType *getTypeArgStorage(); - const QualType *getTypeArgStorage() const { - return const_cast<ObjCObjectType *>(this)->getTypeArgStorage(); - } - - ObjCProtocolDecl **getProtocolStorage(); - -protected: - ObjCObjectType(QualType Canonical, QualType Base, - ArrayRef<QualType> typeArgs, - ArrayRef<ObjCProtocolDecl *> protocols, - bool isKindOf); - - enum Nonce_ObjCInterface { Nonce_ObjCInterface }; - ObjCObjectType(enum Nonce_ObjCInterface) - : Type(ObjCInterface, QualType(), false, false, false, false), - BaseType(QualType(this_(), 0)) { - ObjCObjectTypeBits.NumProtocols = 0; - ObjCObjectTypeBits.NumTypeArgs = 0; - ObjCObjectTypeBits.IsKindOf = 0; - } - - void computeSuperClassTypeSlow() const; - -public: - /// Gets the base type of this object type. This is always (possibly - /// sugar for) one of: - /// - the 'id' builtin type (as opposed to the 'id' type visible to the - /// user, which is a typedef for an ObjCObjectPointerType) - /// - the 'Class' builtin type (same caveat) - /// - an ObjCObjectType (currently always an ObjCInterfaceType) - QualType getBaseType() const { return BaseType; } - - bool isObjCId() const { - return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); - } - bool isObjCClass() const { - return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); - } - bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } - bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } - bool isObjCUnqualifiedIdOrClass() const { - if (!qual_empty()) return false; - if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>()) - return T->getKind() == BuiltinType::ObjCId || - T->getKind() == BuiltinType::ObjCClass; - return false; - } - bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } - bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); } - - /// Gets the interface declaration for this object type, if the base type - /// really is an interface. - ObjCInterfaceDecl *getInterface() const; - - /// Determine whether this object type is "specialized", meaning - /// that it has type arguments. - bool isSpecialized() const; - - /// Determine whether this object type was written with type arguments. - bool isSpecializedAsWritten() const { - return ObjCObjectTypeBits.NumTypeArgs > 0; - } - - /// Determine whether this object type is "unspecialized", meaning - /// that it has no type arguments. - bool isUnspecialized() const { return !isSpecialized(); } - - /// Determine whether this object type is "unspecialized" as - /// written, meaning that it has no type arguments. - bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); } - - /// Retrieve the type arguments of this object type (semantically). - ArrayRef<QualType> getTypeArgs() const; - - /// Retrieve the type arguments of this object type as they were - /// written. - ArrayRef<QualType> getTypeArgsAsWritten() const { - return llvm::makeArrayRef(getTypeArgStorage(), - ObjCObjectTypeBits.NumTypeArgs); - } - - typedef ObjCProtocolDecl * const *qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; - - qual_range quals() const { return qual_range(qual_begin(), qual_end()); } - qual_iterator qual_begin() const { return getProtocolStorage(); } - qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } - - bool qual_empty() const { return getNumProtocols() == 0; } - - /// Return the number of qualifying protocols in this interface type, - /// or 0 if there are none. - unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; } - - /// Fetch a protocol by index. - ObjCProtocolDecl *getProtocol(unsigned I) const { - assert(I < getNumProtocols() && "Out-of-range protocol access"); - return qual_begin()[I]; - } - - /// Retrieve all of the protocol qualifiers. - ArrayRef<ObjCProtocolDecl *> getProtocols() const { - return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols()); - } - - /// Whether this is a "__kindof" type as written. - bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; } - - /// Whether this ia a "__kindof" type (semantically). - bool isKindOfType() const; - - /// Retrieve the type of the superclass of this object type. - /// - /// This operation substitutes any type arguments into the - /// superclass of the current class type, potentially producing a - /// specialization of the superclass type. Produces a null type if - /// there is no superclass. - QualType getSuperClassType() const { - if (!CachedSuperClassType.getInt()) - computeSuperClassTypeSlow(); - - assert(CachedSuperClassType.getInt() && "Superclass not set?"); - return QualType(CachedSuperClassType.getPointer(), 0); - } - - /// Strip off the Objective-C "kindof" type and (with it) any - /// protocol qualifiers. - QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const; - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == ObjCObject || - T->getTypeClass() == ObjCInterface; - } -}; - -/// A class providing a concrete implementation -/// of ObjCObjectType, so as to not increase the footprint of -/// ObjCInterfaceType. Code outside of ASTContext and the core type -/// system should not reference this type. -class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { - friend class ASTContext; - - // If anyone adds fields here, ObjCObjectType::getProtocolStorage() - // will need to be modified. - - ObjCObjectTypeImpl(QualType Canonical, QualType Base, - ArrayRef<QualType> typeArgs, - ArrayRef<ObjCProtocolDecl *> protocols, - bool isKindOf) - : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {} - -public: - void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - QualType Base, - ArrayRef<QualType> typeArgs, - ArrayRef<ObjCProtocolDecl *> protocols, - bool isKindOf); -}; - -inline QualType *ObjCObjectType::getTypeArgStorage() { - return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1); -} - -inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { - return reinterpret_cast<ObjCProtocolDecl**>( - getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); -} - -/// Interfaces are the core concept in Objective-C for object oriented design. -/// They basically correspond to C++ classes. There are two kinds of interface -/// types: normal interfaces like `NSString`, and qualified interfaces, which -/// are qualified with a protocol list like `NSString<NSCopyable, NSAmazing>`. -/// -/// ObjCInterfaceType guarantees the following properties when considered -/// as a subtype of its superclass, ObjCObjectType: -/// - There are no protocol qualifiers. To reinforce this, code which -/// tries to invoke the protocol methods via an ObjCInterfaceType will -/// fail to compile. -/// - It is its own base type. That is, if T is an ObjCInterfaceType*, -/// T->getBaseType() == QualType(T, 0). -class ObjCInterfaceType : public ObjCObjectType { - mutable ObjCInterfaceDecl *Decl; - - ObjCInterfaceType(const ObjCInterfaceDecl *D) - : ObjCObjectType(Nonce_ObjCInterface), - Decl(const_cast<ObjCInterfaceDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; - friend class ObjCInterfaceDecl; - -public: - /// Get the declaration of this interface. - ObjCInterfaceDecl *getDecl() const { return Decl; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == ObjCInterface; - } - - // Nonsense to "hide" certain members of ObjCObjectType within this - // class. People asking for protocols on an ObjCInterfaceType are - // not going to get what they want: ObjCInterfaceTypes are - // guaranteed to have no protocols. - enum { - qual_iterator, - qual_begin, - qual_end, - getNumProtocols, - getProtocol - }; -}; - -inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { - QualType baseType = getBaseType(); - while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) { - if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT)) - return T->getDecl(); - - baseType = ObjT->getBaseType(); - } - - return nullptr; -} - -/// Represents a pointer to an Objective C object. -/// -/// These are constructed from pointer declarators when the pointee type is -/// an ObjCObjectType (or sugar for one). In addition, the 'id' and 'Class' -/// types are typedefs for these, and the protocol-qualified types 'id<P>' -/// and 'Class<P>' are translated into these. -/// -/// Pointers to pointers to Objective C objects are still PointerTypes; -/// only the first level of pointer gets it own type implementation. -class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; - - ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, - Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) {} - friend class ASTContext; // ASTContext creates these. - -public: - /// Gets the type pointed to by this ObjC pointer. - /// The result will always be an ObjCObjectType or sugar thereof. - QualType getPointeeType() const { return PointeeType; } - - /// Gets the type pointed to by this ObjC pointer. Always returns non-null. - /// - /// This method is equivalent to getPointeeType() except that - /// it discards any typedefs (or other sugar) between this - /// type and the "outermost" object type. So for: - /// \code - /// \@class A; \@protocol P; \@protocol Q; - /// typedef A<P> AP; - /// typedef A A1; - /// typedef A1<P> A1P; - /// typedef A1P<Q> A1PQ; - /// \endcode - /// For 'A*', getObjectType() will return 'A'. - /// For 'A<P>*', getObjectType() will return 'A<P>'. - /// For 'AP*', getObjectType() will return 'A<P>'. - /// For 'A1*', getObjectType() will return 'A'. - /// For 'A1<P>*', getObjectType() will return 'A1<P>'. - /// For 'A1P*', getObjectType() will return 'A1<P>'. - /// For 'A1PQ*', getObjectType() will return 'A1<Q>', because - /// adding protocols to a protocol-qualified base discards the - /// old qualifiers (for now). But if it didn't, getObjectType() - /// would return 'A1P<Q>' (and we'd have to make iterating over - /// qualifiers more complicated). - const ObjCObjectType *getObjectType() const { - return PointeeType->castAs<ObjCObjectType>(); - } - - /// If this pointer points to an Objective C - /// \@interface type, gets the type for that interface. Any protocol - /// qualifiers on the interface are ignored. - /// - /// \return null if the base type for this pointer is 'id' or 'Class' - const ObjCInterfaceType *getInterfaceType() const; - - /// If this pointer points to an Objective \@interface - /// type, gets the declaration for that interface. - /// - /// \return null if the base type for this pointer is 'id' or 'Class' - ObjCInterfaceDecl *getInterfaceDecl() const { - return getObjectType()->getInterface(); - } - - /// True if this is equivalent to the 'id' type, i.e. if - /// its object type is the primitive 'id' type with no protocols. - bool isObjCIdType() const { - return getObjectType()->isObjCUnqualifiedId(); - } - - /// True if this is equivalent to the 'Class' type, - /// i.e. if its object tive is the primitive 'Class' type with no protocols. - bool isObjCClassType() const { - return getObjectType()->isObjCUnqualifiedClass(); - } - - /// True if this is equivalent to the 'id' or 'Class' type, - bool isObjCIdOrClassType() const { - return getObjectType()->isObjCUnqualifiedIdOrClass(); - } - - /// True if this is equivalent to 'id<P>' for some non-empty set of - /// protocols. - bool isObjCQualifiedIdType() const { - return getObjectType()->isObjCQualifiedId(); - } - - /// True if this is equivalent to 'Class<P>' for some non-empty set of - /// protocols. - bool isObjCQualifiedClassType() const { - return getObjectType()->isObjCQualifiedClass(); - } - - /// Whether this is a "__kindof" type. - bool isKindOfType() const { return getObjectType()->isKindOfType(); } - - /// Whether this type is specialized, meaning that it has type arguments. - bool isSpecialized() const { return getObjectType()->isSpecialized(); } - - /// Whether this type is specialized, meaning that it has type arguments. - bool isSpecializedAsWritten() const { - return getObjectType()->isSpecializedAsWritten(); - } - - /// Whether this type is unspecialized, meaning that is has no type arguments. - bool isUnspecialized() const { return getObjectType()->isUnspecialized(); } - - /// Determine whether this object type is "unspecialized" as - /// written, meaning that it has no type arguments. - bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); } - - /// Retrieve the type arguments for this type. - ArrayRef<QualType> getTypeArgs() const { - return getObjectType()->getTypeArgs(); - } - - /// Retrieve the type arguments for this type. - ArrayRef<QualType> getTypeArgsAsWritten() const { - return getObjectType()->getTypeArgsAsWritten(); - } - - /// An iterator over the qualifiers on the object type. Provided - /// for convenience. This will always iterate over the full set of - /// protocols on a type, not just those provided directly. - typedef ObjCObjectType::qual_iterator qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; - - qual_range quals() const { return qual_range(qual_begin(), qual_end()); } - qual_iterator qual_begin() const { - return getObjectType()->qual_begin(); - } - qual_iterator qual_end() const { - return getObjectType()->qual_end(); - } - bool qual_empty() const { return getObjectType()->qual_empty(); } - - /// Return the number of qualifying protocols on the object type. - unsigned getNumProtocols() const { - return getObjectType()->getNumProtocols(); - } - - /// Retrieve a qualifying protocol by index on the object type. - ObjCProtocolDecl *getProtocol(unsigned I) const { - return getObjectType()->getProtocol(I); - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - /// Retrieve the type of the superclass of this object pointer type. - /// - /// This operation substitutes any type arguments into the - /// superclass of the current class type, potentially producing a - /// pointer to a specialization of the superclass type. Produces a - /// null type if there is no superclass. - QualType getSuperClassType() const; - - /// Strip off the Objective-C "kindof" type and (with it) any - /// protocol qualifiers. - const ObjCObjectPointerType *stripObjCKindOfTypeAndQuals( - const ASTContext &ctx) const; - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { - ID.AddPointer(T.getAsOpaquePtr()); - } - static bool classof(const Type *T) { - return T->getTypeClass() == ObjCObjectPointer; - } -}; - -class AtomicType : public Type, public llvm::FoldingSetNode { - QualType ValueType; - - AtomicType(QualType ValTy, QualType Canonical) - : Type(Atomic, Canonical, ValTy->isDependentType(), - ValTy->isInstantiationDependentType(), - ValTy->isVariablyModifiedType(), - ValTy->containsUnexpandedParameterPack()), - ValueType(ValTy) {} - friend class ASTContext; // ASTContext creates these. - - public: - /// Gets the type contained by this atomic type, i.e. - /// the type returned by performing an atomic load of this atomic type. - QualType getValueType() const { return ValueType; } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getValueType()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { - ID.AddPointer(T.getAsOpaquePtr()); - } - static bool classof(const Type *T) { - return T->getTypeClass() == Atomic; - } -}; - -/// A qualifier set is used to build a set of qualifiers. -class QualifierCollector : public Qualifiers { -public: - QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {} - - /// Collect any qualifiers on the given type and return an - /// 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(const ASTContext &Context, QualType QT) const; - - /// Apply the collected qualifiers to the given type. - QualType apply(const ASTContext &Context, const Type* T) const; -}; - - -// Inline function definitions. - -inline SplitQualType SplitQualType::getSingleStepDesugaredType() const { - SplitQualType desugar = - Ty->getLocallyUnqualifiedSingleStepDesugaredType().split(); - desugar.Quals.addConsistentQualifiers(Quals); - return desugar; -} - -inline const Type *QualType::getTypePtr() const { - return getCommonPtr()->BaseType; -} - -inline const Type *QualType::getTypePtrOrNull() const { - return (isNull() ? nullptr : 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 { - return getTypePtr()->isCanonicalUnqualified(); -} - -inline bool QualType::isCanonicalAsParam() const { - if (!isCanonical()) return false; - if (hasLocalQualifiers()) return false; - - const Type *T = getTypePtr(); - if (T->isVariablyModifiedType() && T->hasSizedVLAType()) - return false; - - return !isa<FunctionType>(T) && !isa<ArrayType>(T); -} - -inline bool QualType::isConstQualified() const { - return isLocalConstQualified() || - getCommonPtr()->CanonicalType.isLocalConstQualified(); -} - -inline bool QualType::isRestrictQualified() const { - return isLocalRestrictQualified() || - getCommonPtr()->CanonicalType.isLocalRestrictQualified(); -} - - -inline bool QualType::isVolatileQualified() const { - return isLocalVolatileQualified() || - getCommonPtr()->CanonicalType.isLocalVolatileQualified(); -} - -inline bool QualType::hasQualifiers() const { - return hasLocalQualifiers() || - getCommonPtr()->CanonicalType.hasLocalQualifiers(); -} - -inline QualType QualType::getUnqualifiedType() const { - if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) - return QualType(getTypePtr(), 0); - - return QualType(getSplitUnqualifiedTypeImpl(*this).Ty, 0); -} - -inline SplitQualType QualType::getSplitUnqualifiedType() const { - if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) - return split(); - - return getSplitUnqualifiedTypeImpl(*this); -} - -inline void QualType::removeLocalConst() { - removeLocalFastQualifiers(Qualifiers::Const); -} - -inline void QualType::removeLocalRestrict() { - removeLocalFastQualifiers(Qualifiers::Restrict); -} - -inline void QualType::removeLocalVolatile() { - removeLocalFastQualifiers(Qualifiers::Volatile); -} - -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. - removeLocalFastQualifiers(Mask); -} - -/// Return the address space of this type. -inline unsigned QualType::getAddressSpace() const { - return getQualifiers().getAddressSpace(); -} - -/// Return the gc attribute of this type. -inline Qualifiers::GC QualType::getObjCGCAttr() const { - return getQualifiers().getObjCGCAttr(); -} - -inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { - if (const PointerType *PT = t.getAs<PointerType>()) { - if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) - return FT->getExtInfo(); - } else if (const FunctionType *FT = t.getAs<FunctionType>()) - return FT->getExtInfo(); - - return FunctionType::ExtInfo(); -} - -inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { - return getFunctionExtInfo(*t); -} - -/// Determine whether this type is more -/// qualified than the Other type. For example, "const volatile int" -/// 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 { - Qualifiers myQuals = getQualifiers(); - Qualifiers otherQuals = other.getQualifiers(); - return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals)); -} - -/// 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 { - return getQualifiers().compatiblyIncludes(other.getQualifiers()); -} - -/// If Type is a reference type (e.g., const -/// int&), returns the type that the reference refers to ("const -/// int"). Otherwise, returns the type itself. This routine is used -/// throughout Sema to implement C++ 5p6: -/// -/// If an expression initially has the type "reference to T" (8.3.2, -/// 8.5.3), the type is adjusted to "T" prior to any further -/// analysis, the expression designates the object or function -/// denoted by the reference, and the expression is an lvalue. -inline QualType QualType::getNonReferenceType() const { - if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>()) - return RefType->getPointeeType(); - else - return *this; -} - -inline bool QualType::isCForbiddenLValueType() const { - return ((getTypePtr()->isVoidType() && !hasQualifiers()) || - getTypePtr()->isFunctionType()); -} - -/// Tests whether the type is categorized as a fundamental type. -/// -/// \returns True for types specified in C++0x [basic.fundamental]. -inline bool Type::isFundamentalType() const { - return isVoidType() || - // FIXME: It's really annoying that we don't have an - // 'isArithmeticType()' which agrees with the standard definition. - (isArithmeticType() && !isEnumeralType()); -} - -/// Tests whether the type is categorized as a compound type. -/// -/// \returns True for types specified in C++0x [basic.compound]. -inline bool Type::isCompoundType() const { - // C++0x [basic.compound]p1: - // Compound types can be constructed in the following ways: - // -- arrays of objects of a given type [...]; - return isArrayType() || - // -- functions, which have parameters of given types [...]; - isFunctionType() || - // -- pointers to void or objects or functions [...]; - isPointerType() || - // -- references to objects or functions of a given type. [...] - isReferenceType() || - // -- classes containing a sequence of objects of various types, [...]; - isRecordType() || - // -- unions, which are classes capable of containing objects of different - // types at different times; - isUnionType() || - // -- enumerations, which comprise a set of named constant values. [...]; - isEnumeralType() || - // -- pointers to non-static class members, [...]. - isMemberPointerType(); -} - -inline bool Type::isFunctionType() const { - return isa<FunctionType>(CanonicalType); -} -inline bool Type::isPointerType() const { - return isa<PointerType>(CanonicalType); -} -inline bool Type::isAnyPointerType() const { - return isPointerType() || isObjCObjectPointerType(); -} -inline bool Type::isBlockPointerType() const { - return isa<BlockPointerType>(CanonicalType); -} -inline bool Type::isReferenceType() const { - return isa<ReferenceType>(CanonicalType); -} -inline bool Type::isLValueReferenceType() const { - return isa<LValueReferenceType>(CanonicalType); -} -inline bool Type::isRValueReferenceType() const { - return isa<RValueReferenceType>(CanonicalType); -} -inline bool Type::isFunctionPointerType() const { - if (const PointerType *T = getAs<PointerType>()) - return T->getPointeeType()->isFunctionType(); - else - return false; -} -inline bool Type::isMemberPointerType() const { - return isa<MemberPointerType>(CanonicalType); -} -inline bool Type::isMemberFunctionPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) - return T->isMemberFunctionPointer(); - else - return false; -} -inline bool Type::isMemberDataPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) - return T->isMemberDataPointer(); - else - return false; -} -inline bool Type::isArrayType() const { - return isa<ArrayType>(CanonicalType); -} -inline bool Type::isConstantArrayType() const { - return isa<ConstantArrayType>(CanonicalType); -} -inline bool Type::isIncompleteArrayType() const { - return isa<IncompleteArrayType>(CanonicalType); -} -inline bool Type::isVariableArrayType() const { - return isa<VariableArrayType>(CanonicalType); -} -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); -} -inline bool Type::isVectorType() const { - return isa<VectorType>(CanonicalType); -} -inline bool Type::isExtVectorType() const { - return isa<ExtVectorType>(CanonicalType); -} -inline bool Type::isObjCObjectPointerType() const { - return isa<ObjCObjectPointerType>(CanonicalType); -} -inline bool Type::isObjCObjectType() const { - return isa<ObjCObjectType>(CanonicalType); -} -inline bool Type::isObjCObjectOrInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType) || - isa<ObjCObjectType>(CanonicalType); -} -inline bool Type::isAtomicType() const { - return isa<AtomicType>(CanonicalType); -} - -inline bool Type::isObjCQualifiedIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) - return OPT->isObjCQualifiedIdType(); - return false; -} -inline bool Type::isObjCQualifiedClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) - return OPT->isObjCQualifiedClassType(); - return false; -} -inline bool Type::isObjCIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) - return OPT->isObjCIdType(); - return false; -} -inline bool Type::isObjCClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) - return OPT->isObjCClassType(); - return false; -} -inline bool Type::isObjCSelType() const { - if (const PointerType *OPT = getAs<PointerType>()) - return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); - return false; -} -inline bool Type::isObjCBuiltinType() const { - return isObjCIdType() || isObjCClassType() || isObjCSelType(); -} - -inline bool Type::isImage1dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1d); -} - -inline bool Type::isImage1dArrayT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1dArray); -} - -inline bool Type::isImage1dBufferT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1dBuffer); -} - -inline bool Type::isImage2dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2d); -} - -inline bool Type::isImage2dArrayT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArray); -} - -inline bool Type::isImage2dDepthT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth); -} - -inline bool Type::isImage2dArrayDepthT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth); -} - -inline bool Type::isImage2dMSAAT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA); -} - -inline bool Type::isImage2dArrayMSAAT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA); -} - -inline bool Type::isImage2dMSAATDepth() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth); -} - -inline bool Type::isImage2dArrayMSAATDepth() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth); -} - -inline bool Type::isImage3dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage3d); -} - -inline bool Type::isSamplerT() const { - return isSpecificBuiltinType(BuiltinType::OCLSampler); -} - -inline bool Type::isEventT() const { - return isSpecificBuiltinType(BuiltinType::OCLEvent); -} - -inline bool Type::isClkEventT() const { - return isSpecificBuiltinType(BuiltinType::OCLClkEvent); -} - -inline bool Type::isQueueT() const { - return isSpecificBuiltinType(BuiltinType::OCLQueue); -} - -inline bool Type::isNDRangeT() const { - return isSpecificBuiltinType(BuiltinType::OCLNDRange); -} - -inline bool Type::isReserveIDT() const { - return isSpecificBuiltinType(BuiltinType::OCLReserveID); -} - -inline bool Type::isImageType() const { - return isImage3dT() || isImage2dT() || isImage2dArrayT() || - isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() || - isImage2dArrayMSAAT() || isImage2dMSAATDepth() || - isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() || - isImage1dBufferT(); -} - -inline bool Type::isOpenCLSpecificType() const { - return isSamplerT() || isEventT() || isImageType() || isClkEventT() || - isQueueT() || isNDRangeT() || isReserveIDT(); -} - -inline bool Type::isTemplateTypeParmType() const { - return isa<TemplateTypeParmType>(CanonicalType); -} - -inline bool Type::isSpecificBuiltinType(unsigned K) const { - if (const BuiltinType *BT = getAs<BuiltinType>()) - if (BT->getKind() == (BuiltinType::Kind) K) - return true; - return false; -} - -inline bool Type::isPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) - return BT->isPlaceholderType(); - return false; -} - -inline const BuiltinType *Type::getAsPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) - if (BT->isPlaceholderType()) - return BT; - return nullptr; -} - -inline bool Type::isSpecificPlaceholderType(unsigned K) const { - assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K)); - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) - return (BT->getKind() == (BuiltinType::Kind) K); - return false; -} - -inline bool Type::isNonOverloadPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) - return BT->isNonOverloadPlaceholderType(); - return false; -} - -inline bool Type::isVoidType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Void; - return false; -} - -inline bool Type::isHalfType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Half; - // FIXME: Should we allow complex __fp16? Probably not. - return false; -} - -inline bool Type::isNullPtrType() const { - if (const BuiltinType *BT = getAs<BuiltinType>()) - return BT->getKind() == BuiltinType::NullPtr; - return false; -} - -extern bool IsEnumDeclComplete(EnumDecl *); -extern bool IsEnumDeclScoped(EnumDecl *); - -inline bool Type::isIntegerType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { - // Incomplete enum types are not treated as integer types. - // FIXME: In C++, enum types are never integer types. - return IsEnumDeclComplete(ET->getDecl()) && - !IsEnumDeclScoped(ET->getDecl()); - } - return false; -} - -inline bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() > BuiltinType::Void && - BT->getKind() <= BuiltinType::NullPtr; - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - // Enums are scalar types, but only if they are defined. Incomplete enums - // are not treated as scalar types. - return IsEnumDeclComplete(ET->getDecl()); - return isa<PointerType>(CanonicalType) || - isa<BlockPointerType>(CanonicalType) || - isa<MemberPointerType>(CanonicalType) || - isa<ComplexType>(CanonicalType) || - isa<ObjCObjectPointerType>(CanonicalType); -} - -inline bool Type::isIntegralOrEnumerationType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - - // Check for a complete enum type; incomplete enum types are not properly an - // enumeration type in the sense required here. - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - return IsEnumDeclComplete(ET->getDecl()); - - return false; -} - -inline bool Type::isBooleanType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Bool; - return false; -} - -inline bool Type::isUndeducedType() const { - const AutoType *AT = getContainedAutoType(); - return AT && !AT->isDeduced(); -} - -/// \brief Determines whether this is a type for which one can define -/// an overloaded operator. -inline bool Type::isOverloadableType() const { - return isDependentType() || isRecordType() || isEnumeralType(); -} - -/// \brief Determines whether this type can decay to a pointer type. -inline bool Type::canDecayToPointerType() const { - return isFunctionType() || isArrayType(); -} - -inline bool Type::hasPointerRepresentation() const { - return (isPointerType() || isReferenceType() || isBlockPointerType() || - isObjCObjectPointerType() || isNullPtrType()); -} - -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, - QualType T) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), - DiagnosticsEngine::ak_qualtype); - return DB; -} - -/// Insertion operator for partial diagnostics. This allows sending QualType's -/// into a diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - QualType T) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), - DiagnosticsEngine::ak_qualtype); - return PD; -} - -// Helper class template that is used by Type::getAs to ensure that one does -// not try to look through a qualified type to get to an array type. -template <typename T, bool isArrayType = (std::is_same<T, ArrayType>::value || - std::is_base_of<ArrayType, T>::value)> -struct ArrayType_cannot_be_used_with_getAs {}; - -template<typename T> -struct ArrayType_cannot_be_used_with_getAs<T, true>; - -// Member-template getAs<specific type>'. -template <typename T> const T *Type::getAs() const { - ArrayType_cannot_be_used_with_getAs<T> at; - (void)at; - - // If this is directly a T type, return it. - if (const T *Ty = dyn_cast<T>(this)) - return Ty; - - // If the canonical form of this type isn't the right kind, reject it. - if (!isa<T>(CanonicalType)) - return nullptr; - - // If this is a typedef for the type, strip the typedef off without - // losing all typedef information. - 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 nullptr; - - // 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; - - if (const T *ty = dyn_cast<T>(this)) return ty; - assert(isa<T>(CanonicalType)); - 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 deleted file mode 100644 index 26feda5..0000000 --- a/include/clang/AST/TypeLoc.h +++ /dev/null @@ -1,2039 +0,0 @@ -//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Defines the clang::TypeLoc interface and its subclasses. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TYPELOC_H -#define LLVM_CLANG_AST_TYPELOC_H - -#include "clang/AST/Decl.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" -#include "clang/Basic/Specifiers.h" -#include "llvm/Support/Compiler.h" - -namespace clang { - class ASTContext; - class ParmVarDecl; - class TypeSourceInfo; - class UnqualTypeLoc; - -// Predeclare all the type nodes. -#define ABSTRACT_TYPELOC(Class, Base) -#define TYPELOC(Class, Base) \ - class Class##TypeLoc; -#include "clang/AST/TypeLocNodes.def" - -/// \brief Base wrapper for a particular "section" of type source info. -/// -/// A client should use the TypeLoc subclasses through castAs()/getAs() -/// in order to get at the actual information. -class TypeLoc { -protected: - // The correctness of this relies on the property that, for Type *Ty, - // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty - const void *Ty; - void *Data; - -public: - /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc - /// is of the desired type. - /// - /// \pre T::isKind(*this) - template<typename T> - T castAs() const { - assert(T::isKind(*this)); - T t; - TypeLoc& tl = t; - tl = *this; - return t; - } - - /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if - /// this TypeLoc is not of the desired type. - template<typename T> - T getAs() const { - if (!T::isKind(*this)) - return T(); - T t; - TypeLoc& tl = t; - tl = *this; - return t; - } - - /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, - /// except it also defines a Qualified enum that corresponds to the - /// QualifiedLoc class. - enum TypeLocClass { -#define ABSTRACT_TYPE(Class, Base) -#define TYPE(Class, Base) \ - Class = Type::Class, -#include "clang/AST/TypeNodes.def" - Qualified - }; - - TypeLoc() : Ty(nullptr), Data(nullptr) { } - TypeLoc(QualType ty, void *opaqueData) - : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } - TypeLoc(const Type *ty, void *opaqueData) - : Ty(ty), Data(opaqueData) { } - - TypeLocClass getTypeLocClass() const { - if (getType().hasLocalQualifiers()) return Qualified; - return (TypeLocClass) getType()->getTypeClass(); - } - - bool isNull() const { return !Ty; } - explicit operator bool() const { return Ty; } - - /// \brief Returns the size of type source info data block for the given type. - static unsigned getFullDataSizeForType(QualType Ty); - - /// \brief Returns the alignment of type source info data block for - /// the given type. - static unsigned getLocalAlignmentForType(QualType Ty); - - /// \brief Get the type for which this source info wrapper provides - /// information. - QualType getType() const { - return QualType::getFromOpaquePtr(Ty); - } - - const Type *getTypePtr() const { - return QualType::getFromOpaquePtr(Ty).getTypePtr(); - } - - /// \brief Get the pointer where source information is stored. - void *getOpaqueData() const { - return Data; - } - - /// \brief Get the begin source location. - SourceLocation getBeginLoc() const; - - /// \brief Get the end source location. - SourceLocation getEndLoc() const; - - /// \brief Get the full source range. - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getBeginLoc(), getEndLoc()); - } - SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - - /// \brief Get the local source range. - SourceRange getLocalSourceRange() const { - return getLocalSourceRangeImpl(*this); - } - - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getFullDataSizeForType(getType()); - } - - /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the - /// TypeLoc is a PointerLoc and next TypeLoc is for "int". - TypeLoc getNextTypeLoc() const { - return getNextTypeLocImpl(*this); - } - - /// \brief Skips past any qualifiers, if this is qualified. - UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header - - TypeLoc IgnoreParens() const; - - /// \brief Find a type with the location of an explicit type qualifier. - /// - /// The result, if non-null, will be one of: - /// QualifiedTypeLoc - /// AtomicTypeLoc - /// AttributedTypeLoc, for those type attributes that behave as qualifiers - TypeLoc findExplicitQualifierLoc() const; - - /// \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(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) { - assert(getType() == Other.getType()); - copy(Other); - } - - /// \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) { - assert(getType() == Other.getType()); - assert(getFullDataSize() == Size); - copy(Other); - } - - /// Copies the other type loc into this one. - void copy(TypeLoc other); - - friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { - return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; - } - - friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) { - return !(LHS == RHS); - } - - /// Find the location of the nullability specifier (__nonnull, - /// __nullable, or __null_unspecifier), if there is one. - SourceLocation findNullabilityLoc() const; - -private: - static bool isKind(const TypeLoc&) { - return true; - } - - static void initializeImpl(ASTContext &Context, TypeLoc TL, - SourceLocation Loc); - static TypeLoc getNextTypeLocImpl(TypeLoc TL); - static TypeLoc IgnoreParensImpl(TypeLoc TL); - static SourceRange getLocalSourceRangeImpl(TypeLoc TL); -}; - -/// \brief Return the TypeLoc for a type source info. -inline TypeLoc TypeSourceInfo::getTypeLoc() const { - // TODO: is this alignment already sufficient? - return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); -} - -/// \brief Wrapper of type source information for a type with -/// no direct qualifiers. -class UnqualTypeLoc : public TypeLoc { -public: - UnqualTypeLoc() {} - UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} - - const Type *getTypePtr() const { - return reinterpret_cast<const Type*>(Ty); - } - - TypeLocClass getTypeLocClass() const { - return (TypeLocClass) getTypePtr()->getTypeClass(); - } - -private: - friend class TypeLoc; - static bool isKind(const TypeLoc &TL) { - return !TL.getType().hasLocalQualifiers(); - } -}; - -/// \brief Wrapper of type source information for a type with -/// non-trivial direct qualifiers. -/// -/// Currently, we intentionally do not provide source location for -/// type qualifiers. -class QualifiedTypeLoc : public TypeLoc { -public: - SourceRange getLocalSourceRange() const { - return SourceRange(); - } - - UnqualTypeLoc getUnqualifiedLoc() const { - unsigned align = - TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0)); - uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data); - dataInt = llvm::RoundUpToAlignment(dataInt, align); - return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt)); - } - - /// Initializes the local data of this type source info block to - /// provide no information. - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - // do nothing - } - - void copyLocal(TypeLoc other) { - // do nothing - } - - TypeLoc getNextTypeLoc() const { - return getUnqualifiedLoc(); - } - - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { - // In fact, we don't currently preserve any location information - // for qualifiers. - return 0; - } - - /// \brief Returns the alignment of the type source info data block that is - /// specific to this type. - unsigned getLocalDataAlignment() const { - // We don't preserve any location information. - return 1; - } - -private: - friend class TypeLoc; - static bool isKind(const TypeLoc &TL) { - return TL.getType().hasLocalQualifiers(); - } -}; - -inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { - if (QualifiedTypeLoc Loc = getAs<QualifiedTypeLoc>()) - return Loc.getUnqualifiedLoc(); - return castAs<UnqualTypeLoc>(); -} - -/// A metaprogramming base class for TypeLoc classes which correspond -/// to a particular Type subclass. It is accepted for a single -/// TypeLoc class to correspond to multiple Type classes. -/// -/// \tparam Base a class from which to derive -/// \tparam Derived the class deriving from this one -/// \tparam TypeClass the concrete Type subclass associated with this -/// location type -/// \tparam LocalData the structure type of local location data for -/// this type -/// -/// TypeLocs with non-constant amounts of local data should override -/// getExtraLocalDataSize(); getExtraLocalData() will then point to -/// this extra memory. -/// -/// TypeLocs with an inner type should define -/// QualType getInnerType() const -/// and getInnerTypeLoc() will then point to this inner type's -/// location data. -/// -/// A word about hierarchies: this template is not designed to be -/// derived from multiple times in a hierarchy. It is also not -/// designed to be used for classes where subtypes might provide -/// different amounts of source information. It should be subclassed -/// only at the deepest portion of the hierarchy where all children -/// have identical source information; if that's an abstract type, -/// then further descendents should inherit from -/// InheritingConcreteTypeLoc instead. -template <class Base, class Derived, class TypeClass, class LocalData> -class ConcreteTypeLoc : public Base { - - const Derived *asDerived() const { - return static_cast<const Derived*>(this); - } - - friend class TypeLoc; - static bool isKind(const TypeLoc &TL) { - return !TL.getType().hasLocalQualifiers() && - Derived::classofType(TL.getTypePtr()); - } - - static bool classofType(const Type *Ty) { - return TypeClass::classof(Ty); - } - -public: - unsigned getLocalDataAlignment() const { - return std::max(llvm::alignOf<LocalData>(), - asDerived()->getExtraLocalDataAlignment()); - } - unsigned getLocalDataSize() const { - unsigned size = sizeof(LocalData); - unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); - size = llvm::RoundUpToAlignment(size, extraAlign); - size += asDerived()->getExtraLocalDataSize(); - return size; - } - - void copyLocal(Derived other) { - // Some subclasses have no data to copy. - if (asDerived()->getLocalDataSize() == 0) return; - - // Copy the fixed-sized local data. - memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData)); - - // Copy the variable-sized local data. We need to do this - // separately because the padding in the source and the padding in - // the destination might be different. - memcpy(getExtraLocalData(), other.getExtraLocalData(), - asDerived()->getExtraLocalDataSize()); - } - - TypeLoc getNextTypeLoc() const { - return getNextTypeLoc(asDerived()->getInnerType()); - } - - const TypeClass *getTypePtr() const { - return cast<TypeClass>(Base::getTypePtr()); - } - -protected: - unsigned getExtraLocalDataSize() const { - return 0; - } - - unsigned getExtraLocalDataAlignment() const { - return 1; - } - - LocalData *getLocalData() const { - return static_cast<LocalData*>(Base::Data); - } - - /// Gets a pointer past the Info structure; useful for classes with - /// local data that can't be captured in the Info (e.g. because it's - /// of variable size). - void *getExtraLocalData() const { - unsigned size = sizeof(LocalData); - unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); - size = llvm::RoundUpToAlignment(size, extraAlign); - return reinterpret_cast<char*>(Base::Data) + size; - } - - void *getNonLocalData() const { - uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data); - data += asDerived()->getLocalDataSize(); - data = llvm::RoundUpToAlignment(data, getNextTypeAlign()); - return reinterpret_cast<void*>(data); - } - - struct HasNoInnerType {}; - HasNoInnerType getInnerType() const { return HasNoInnerType(); } - - TypeLoc getInnerTypeLoc() const { - return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); - } - -private: - unsigned getInnerTypeSize() const { - return getInnerTypeSize(asDerived()->getInnerType()); - } - - unsigned getInnerTypeSize(HasNoInnerType _) const { - return 0; - } - - unsigned getInnerTypeSize(QualType _) const { - return getInnerTypeLoc().getFullDataSize(); - } - - unsigned getNextTypeAlign() const { - return getNextTypeAlign(asDerived()->getInnerType()); - } - - unsigned getNextTypeAlign(HasNoInnerType _) const { - return 1; - } - - unsigned getNextTypeAlign(QualType T) const { - return TypeLoc::getLocalAlignmentForType(T); - } - - TypeLoc getNextTypeLoc(HasNoInnerType _) const { - return TypeLoc(); - } - - TypeLoc getNextTypeLoc(QualType T) const { - return TypeLoc(T, getNonLocalData()); - } -}; - -/// A metaprogramming class designed for concrete subtypes of abstract -/// types where all subtypes share equivalently-structured source -/// information. See the note on ConcreteTypeLoc. -template <class Base, class Derived, class TypeClass> -class InheritingConcreteTypeLoc : public Base { - friend class TypeLoc; - static bool classofType(const Type *Ty) { - return TypeClass::classof(Ty); - } - - static bool isKind(const TypeLoc &TL) { - return !TL.getType().hasLocalQualifiers() && - Derived::classofType(TL.getTypePtr()); - } - static bool isKind(const UnqualTypeLoc &TL) { - return Derived::classofType(TL.getTypePtr()); - } - -public: - const TypeClass *getTypePtr() const { - return cast<TypeClass>(Base::getTypePtr()); - } -}; - - -struct TypeSpecLocInfo { - SourceLocation NameLoc; -}; - -/// \brief A reasonable base class for TypeLocs that correspond to -/// types that are written as a type-specifier. -class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - TypeSpecTypeLoc, - Type, - TypeSpecLocInfo> { -public: - enum { LocalDataSize = sizeof(TypeSpecLocInfo), - LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment }; - - SourceLocation getNameLoc() const { - return this->getLocalData()->NameLoc; - } - void setNameLoc(SourceLocation Loc) { - this->getLocalData()->NameLoc = Loc; - } - SourceRange getLocalSourceRange() const { - return SourceRange(getNameLoc(), getNameLoc()); - } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setNameLoc(Loc); - } - -private: - friend class TypeLoc; - static bool isKind(const TypeLoc &TL); -}; - - -struct BuiltinLocInfo { - SourceLocation BuiltinLoc; -}; - -/// \brief Wrapper for source info for builtin types. -class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - BuiltinTypeLoc, - BuiltinType, - BuiltinLocInfo> { -public: - SourceLocation getBuiltinLoc() const { - return getLocalData()->BuiltinLoc; - } - void setBuiltinLoc(SourceLocation Loc) { - getLocalData()->BuiltinLoc = Loc; - } - - SourceLocation getNameLoc() const { return getBuiltinLoc(); } - - WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { - return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); - } - const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { - return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); - } - - bool needsExtraLocalData() const { - BuiltinType::Kind bk = getTypePtr()->getKind(); - return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) - || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) - || bk == BuiltinType::UChar - || bk == BuiltinType::SChar; - } - - unsigned getExtraLocalDataSize() const { - return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; - } - - unsigned getExtraLocalDataAlignment() const { - return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1; - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getBuiltinLoc(), getBuiltinLoc()); - } - - TypeSpecifierSign getWrittenSignSpec() const { - if (needsExtraLocalData()) - return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign); - else - return TSS_unspecified; - } - bool hasWrittenSignSpec() const { - return getWrittenSignSpec() != TSS_unspecified; - } - void setWrittenSignSpec(TypeSpecifierSign written) { - if (needsExtraLocalData()) - getWrittenBuiltinSpecs().Sign = written; - } - - TypeSpecifierWidth getWrittenWidthSpec() const { - if (needsExtraLocalData()) - return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width); - else - return TSW_unspecified; - } - bool hasWrittenWidthSpec() const { - return getWrittenWidthSpec() != TSW_unspecified; - } - void setWrittenWidthSpec(TypeSpecifierWidth written) { - if (needsExtraLocalData()) - getWrittenBuiltinSpecs().Width = written; - } - - TypeSpecifierType getWrittenTypeSpec() const; - bool hasWrittenTypeSpec() const { - return getWrittenTypeSpec() != TST_unspecified; - } - void setWrittenTypeSpec(TypeSpecifierType written) { - if (needsExtraLocalData()) - getWrittenBuiltinSpecs().Type = written; - } - - bool hasModeAttr() const { - if (needsExtraLocalData()) - return getWrittenBuiltinSpecs().ModeAttr; - else - return false; - } - void setModeAttr(bool written) { - if (needsExtraLocalData()) - getWrittenBuiltinSpecs().ModeAttr = written; - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setBuiltinLoc(Loc); - if (needsExtraLocalData()) { - WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); - wbs.Sign = TSS_unspecified; - wbs.Width = TSW_unspecified; - wbs.Type = TST_unspecified; - wbs.ModeAttr = false; - } - } -}; - - -/// \brief Wrapper for source info for typedefs. -class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - TypedefTypeLoc, - TypedefType> { -public: - TypedefNameDecl *getTypedefNameDecl() const { - return getTypePtr()->getDecl(); - } -}; - -/// \brief Wrapper for source info for injected class names of class -/// templates. -class InjectedClassNameTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - InjectedClassNameTypeLoc, - InjectedClassNameType> { -public: - CXXRecordDecl *getDecl() const { - return getTypePtr()->getDecl(); - } -}; - -/// \brief Wrapper for source info for unresolved typename using decls. -class UnresolvedUsingTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - UnresolvedUsingTypeLoc, - UnresolvedUsingType> { -public: - UnresolvedUsingTypenameDecl *getDecl() const { - return getTypePtr()->getDecl(); - } -}; - -/// \brief Wrapper for source info for tag types. Note that this only -/// records source info for the name itself; a type written 'struct foo' -/// should be represented as an ElaboratedTypeLoc. We currently -/// only do that when C++ is enabled because of the expense of -/// creating an ElaboratedType node for so many type references in C. -class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - TagTypeLoc, - TagType> { -public: - TagDecl *getDecl() const { return getTypePtr()->getDecl(); } - - /// \brief True if the tag was defined in this type specifier. - bool isDefinition() const { - TagDecl *D = getDecl(); - return D->isCompleteDefinition() && - (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); - } -}; - -/// \brief Wrapper for source info for record types. -class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - RecordTypeLoc, - RecordType> { -public: - RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } -}; - -/// \brief Wrapper for source info for enum types. -class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - EnumTypeLoc, - EnumType> { -public: - EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } -}; - -/// \brief Wrapper for template type parameters. -class TemplateTypeParmTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - TemplateTypeParmTypeLoc, - TemplateTypeParmType> { -public: - TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } -}; - -/// \brief Wrapper for substituted template type parameters. -class SubstTemplateTypeParmTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - 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(); - } - - bool isQualifier() const { - return getTypePtr()->isQualifier(); - } - - /// 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(nullptr); - } else if (hasAttrEnumOperand()) { - setAttrOperandParensRange(SourceRange(loc)); - setAttrEnumOperandLoc(loc); - } - } - - QualType getInnerType() const { - return getTypePtr()->getModifiedType(); - } -}; - - -struct ObjCObjectTypeLocInfo { - SourceLocation TypeArgsLAngleLoc; - SourceLocation TypeArgsRAngleLoc; - SourceLocation ProtocolLAngleLoc; - SourceLocation ProtocolRAngleLoc; - bool HasBaseTypeAsWritten; -}; - -// A helper class for defining ObjC TypeLocs that can qualified with -// protocols. -// -// TypeClass basically has to be either ObjCInterfaceType or -// ObjCObjectPointerType. -class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - ObjCObjectTypeLoc, - ObjCObjectType, - ObjCObjectTypeLocInfo> { - // TypeSourceInfo*'s are stored after Info, one for each type argument. - TypeSourceInfo **getTypeArgLocArray() const { - return (TypeSourceInfo**)this->getExtraLocalData(); - } - - // SourceLocations are stored after the type argument information, one for - // each Protocol. - SourceLocation *getProtocolLocArray() const { - return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs()); - } - -public: - SourceLocation getTypeArgsLAngleLoc() const { - return this->getLocalData()->TypeArgsLAngleLoc; - } - void setTypeArgsLAngleLoc(SourceLocation Loc) { - this->getLocalData()->TypeArgsLAngleLoc = Loc; - } - - SourceLocation getTypeArgsRAngleLoc() const { - return this->getLocalData()->TypeArgsRAngleLoc; - } - void setTypeArgsRAngleLoc(SourceLocation Loc) { - this->getLocalData()->TypeArgsRAngleLoc = Loc; - } - - unsigned getNumTypeArgs() const { - return this->getTypePtr()->getTypeArgsAsWritten().size(); - } - - TypeSourceInfo *getTypeArgTInfo(unsigned i) const { - assert(i < getNumTypeArgs() && "Index is out of bounds!"); - return getTypeArgLocArray()[i]; - } - - void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) { - assert(i < getNumTypeArgs() && "Index is out of bounds!"); - getTypeArgLocArray()[i] = TInfo; - } - - SourceLocation getProtocolLAngleLoc() const { - return this->getLocalData()->ProtocolLAngleLoc; - } - void setProtocolLAngleLoc(SourceLocation Loc) { - this->getLocalData()->ProtocolLAngleLoc = Loc; - } - - SourceLocation getProtocolRAngleLoc() const { - return this->getLocalData()->ProtocolRAngleLoc; - } - void setProtocolRAngleLoc(SourceLocation Loc) { - this->getLocalData()->ProtocolRAngleLoc = Loc; - } - - unsigned getNumProtocols() const { - return this->getTypePtr()->getNumProtocols(); - } - - SourceLocation getProtocolLoc(unsigned i) const { - assert(i < getNumProtocols() && "Index is out of bounds!"); - return getProtocolLocArray()[i]; - } - void setProtocolLoc(unsigned i, SourceLocation Loc) { - assert(i < getNumProtocols() && "Index is out of bounds!"); - getProtocolLocArray()[i] = Loc; - } - - ObjCProtocolDecl *getProtocol(unsigned i) const { - assert(i < getNumProtocols() && "Index is out of bounds!"); - return *(this->getTypePtr()->qual_begin() + i); - } - - - ArrayRef<SourceLocation> getProtocolLocs() const { - return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); - } - - bool hasBaseTypeAsWritten() const { - return getLocalData()->HasBaseTypeAsWritten; - } - - void setHasBaseTypeAsWritten(bool HasBaseType) { - getLocalData()->HasBaseTypeAsWritten = HasBaseType; - } - - TypeLoc getBaseLoc() const { - return getInnerTypeLoc(); - } - - SourceRange getLocalSourceRange() const { - SourceLocation start = getTypeArgsLAngleLoc(); - if (start.isInvalid()) - start = getProtocolLAngleLoc(); - SourceLocation end = getProtocolRAngleLoc(); - if (end.isInvalid()) - end = getTypeArgsRAngleLoc(); - return SourceRange(start, end); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc); - - unsigned getExtraLocalDataSize() const { - return this->getNumTypeArgs() * sizeof(TypeSourceInfo *) - + this->getNumProtocols() * sizeof(SourceLocation); - } - - unsigned getExtraLocalDataAlignment() const { - assert(llvm::alignOf<ObjCObjectTypeLoc>() - >= llvm::alignOf<TypeSourceInfo *>() && - "not enough alignment for tail-allocated data"); - return llvm::alignOf<TypeSourceInfo *>(); - } - - QualType getInnerType() const { - return getTypePtr()->getBaseType(); - } -}; - - -struct ObjCInterfaceLocInfo { - SourceLocation NameLoc; - SourceLocation NameEndLoc; -}; - -/// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc, - ObjCInterfaceTypeLoc, - ObjCInterfaceType, - ObjCInterfaceLocInfo> { -public: - ObjCInterfaceDecl *getIFaceDecl() const { - return getTypePtr()->getDecl(); - } - - SourceLocation getNameLoc() const { - return getLocalData()->NameLoc; - } - - void setNameLoc(SourceLocation Loc) { - getLocalData()->NameLoc = Loc; - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getNameLoc(), getNameEndLoc()); - } - - SourceLocation getNameEndLoc() const { - return getLocalData()->NameEndLoc; - } - - void setNameEndLoc(SourceLocation Loc) { - getLocalData()->NameEndLoc = Loc; - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setNameLoc(Loc); - setNameEndLoc(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(); - } -}; - -inline TypeLoc TypeLoc::IgnoreParens() const { - if (ParenTypeLoc::isKind(*this)) - return IgnoreParensImpl(*this); - return *this; -} - - -struct AdjustedLocInfo { }; // Nothing. - -class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, - AdjustedType, AdjustedLocInfo> { -public: - TypeLoc getOriginalLoc() const { - return getInnerTypeLoc(); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - // do nothing - } - - QualType getInnerType() const { - // The inner type is the undecayed type, since that's what we have source - // location information for. - return getTypePtr()->getOriginalType(); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(); - } - - unsigned getLocalDataSize() const { - // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique - // anyway. TypeLocBuilder can't handle data sizes of 1. - return 0; // No data. - } -}; - -/// \brief Wrapper for source info for pointers decayed from arrays and -/// functions. -class DecayedTypeLoc : public InheritingConcreteTypeLoc< - AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { -}; - -struct PointerLikeLocInfo { - SourceLocation StarLoc; -}; - -/// A base class for -template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> -class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, - TypeClass, LocalData> { -public: - SourceLocation getSigilLoc() const { - return this->getLocalData()->StarLoc; - } - void setSigilLoc(SourceLocation Loc) { - this->getLocalData()->StarLoc = Loc; - } - - TypeLoc getPointeeLoc() const { - return this->getInnerTypeLoc(); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getSigilLoc(), getSigilLoc()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setSigilLoc(Loc); - } - - QualType getInnerType() const { - return this->getTypePtr()->getPointeeType(); - } -}; - - -/// \brief Wrapper for source info for pointers. -class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, - PointerType> { -public: - SourceLocation getStarLoc() const { - return getSigilLoc(); - } - void setStarLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - - -/// \brief Wrapper for source info for block pointers. -class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, - BlockPointerType> { -public: - SourceLocation getCaretLoc() const { - return getSigilLoc(); - } - void setCaretLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - -struct MemberPointerLocInfo : public PointerLikeLocInfo { - TypeSourceInfo *ClassTInfo; -}; - -/// \brief Wrapper for source info for member pointers. -class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, - MemberPointerType, - MemberPointerLocInfo> { -public: - SourceLocation getStarLoc() const { - return getSigilLoc(); - } - void setStarLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } - - const Type *getClass() const { - return getTypePtr()->getClass(); - } - TypeSourceInfo *getClassTInfo() const { - return getLocalData()->ClassTInfo; - } - void setClassTInfo(TypeSourceInfo* TI) { - getLocalData()->ClassTInfo = TI; - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setSigilLoc(Loc); - setClassTInfo(nullptr); - } - - SourceRange getLocalSourceRange() const { - if (TypeSourceInfo *TI = getClassTInfo()) - return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); - else - return SourceRange(getStarLoc()); - } -}; - -/// Wraps an ObjCPointerType with source location information. -class ObjCObjectPointerTypeLoc : - public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, - ObjCObjectPointerType> { -public: - SourceLocation getStarLoc() const { - return getSigilLoc(); - } - - void setStarLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - - -class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, - ReferenceType> { -public: - QualType getInnerType() const { - return getTypePtr()->getPointeeTypeAsWritten(); - } -}; - -class LValueReferenceTypeLoc : - public InheritingConcreteTypeLoc<ReferenceTypeLoc, - LValueReferenceTypeLoc, - LValueReferenceType> { -public: - SourceLocation getAmpLoc() const { - return getSigilLoc(); - } - void setAmpLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - -class RValueReferenceTypeLoc : - public InheritingConcreteTypeLoc<ReferenceTypeLoc, - RValueReferenceTypeLoc, - RValueReferenceType> { -public: - SourceLocation getAmpAmpLoc() const { - return getSigilLoc(); - } - void setAmpAmpLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - - -struct FunctionLocInfo { - SourceLocation LocalRangeBegin; - SourceLocation LParenLoc; - SourceLocation RParenLoc; - SourceLocation LocalRangeEnd; -}; - -/// \brief Wrapper for source info for functions. -class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - FunctionTypeLoc, - FunctionType, - FunctionLocInfo> { -public: - SourceLocation getLocalRangeBegin() const { - return getLocalData()->LocalRangeBegin; - } - void setLocalRangeBegin(SourceLocation L) { - getLocalData()->LocalRangeBegin = L; - } - - SourceLocation getLocalRangeEnd() const { - return getLocalData()->LocalRangeEnd; - } - void setLocalRangeEnd(SourceLocation L) { - getLocalData()->LocalRangeEnd = L; - } - - SourceLocation getLParenLoc() const { - return this->getLocalData()->LParenLoc; - } - void setLParenLoc(SourceLocation Loc) { - this->getLocalData()->LParenLoc = Loc; - } - - SourceLocation getRParenLoc() const { - return this->getLocalData()->RParenLoc; - } - void setRParenLoc(SourceLocation Loc) { - this->getLocalData()->RParenLoc = Loc; - } - - SourceRange getParensRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); - } - - ArrayRef<ParmVarDecl *> getParams() const { - return llvm::makeArrayRef(getParmArray(), getNumParams()); - } - - // ParmVarDecls* are stored after Info, one for each parameter. - ParmVarDecl **getParmArray() const { - return (ParmVarDecl**) getExtraLocalData(); - } - - unsigned getNumParams() const { - if (isa<FunctionNoProtoType>(getTypePtr())) - return 0; - return cast<FunctionProtoType>(getTypePtr())->getNumParams(); - } - ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } - void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } - - TypeLoc getReturnLoc() const { - return getInnerTypeLoc(); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setLocalRangeBegin(Loc); - setLParenLoc(Loc); - setRParenLoc(Loc); - setLocalRangeEnd(Loc); - for (unsigned i = 0, e = getNumParams(); i != e; ++i) - setParam(i, nullptr); - } - - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getExtraLocalDataSize() const { - return getNumParams() * sizeof(ParmVarDecl *); - } - - unsigned getExtraLocalDataAlignment() const { - return llvm::alignOf<ParmVarDecl*>(); - } - - QualType getInnerType() const { return getTypePtr()->getReturnType(); } -}; - -class FunctionProtoTypeLoc : - public InheritingConcreteTypeLoc<FunctionTypeLoc, - FunctionProtoTypeLoc, - FunctionProtoType> { -}; - -class FunctionNoProtoTypeLoc : - public InheritingConcreteTypeLoc<FunctionTypeLoc, - FunctionNoProtoTypeLoc, - FunctionNoProtoType> { -}; - - -struct ArrayLocInfo { - SourceLocation LBracketLoc, RBracketLoc; - Expr *Size; -}; - -/// \brief Wrapper for source info for arrays. -class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - ArrayTypeLoc, - ArrayType, - ArrayLocInfo> { -public: - SourceLocation getLBracketLoc() const { - return getLocalData()->LBracketLoc; - } - void setLBracketLoc(SourceLocation Loc) { - getLocalData()->LBracketLoc = Loc; - } - - SourceLocation getRBracketLoc() const { - return getLocalData()->RBracketLoc; - } - void setRBracketLoc(SourceLocation Loc) { - getLocalData()->RBracketLoc = Loc; - } - - SourceRange getBracketsRange() const { - return SourceRange(getLBracketLoc(), getRBracketLoc()); - } - - Expr *getSizeExpr() const { - return getLocalData()->Size; - } - void setSizeExpr(Expr *Size) { - getLocalData()->Size = Size; - } - - TypeLoc getElementLoc() const { - return getInnerTypeLoc(); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getLBracketLoc(), getRBracketLoc()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setLBracketLoc(Loc); - setRBracketLoc(Loc); - setSizeExpr(nullptr); - } - - QualType getInnerType() const { return getTypePtr()->getElementType(); } -}; - -class ConstantArrayTypeLoc : - public InheritingConcreteTypeLoc<ArrayTypeLoc, - ConstantArrayTypeLoc, - ConstantArrayType> { -}; - -class IncompleteArrayTypeLoc : - public InheritingConcreteTypeLoc<ArrayTypeLoc, - IncompleteArrayTypeLoc, - IncompleteArrayType> { -}; - -class DependentSizedArrayTypeLoc : - public InheritingConcreteTypeLoc<ArrayTypeLoc, - DependentSizedArrayTypeLoc, - DependentSizedArrayType> { - -}; - -class VariableArrayTypeLoc : - public InheritingConcreteTypeLoc<ArrayTypeLoc, - VariableArrayTypeLoc, - VariableArrayType> { -}; - - -// Location information for a TemplateName. Rudimentary for now. -struct TemplateNameLocInfo { - SourceLocation NameLoc; -}; - -struct TemplateSpecializationLocInfo : TemplateNameLocInfo { - SourceLocation TemplateKWLoc; - SourceLocation LAngleLoc; - SourceLocation RAngleLoc; -}; - -class TemplateSpecializationTypeLoc : - public ConcreteTypeLoc<UnqualTypeLoc, - TemplateSpecializationTypeLoc, - TemplateSpecializationType, - TemplateSpecializationLocInfo> { -public: - SourceLocation getTemplateKeywordLoc() const { - return getLocalData()->TemplateKWLoc; - } - void setTemplateKeywordLoc(SourceLocation Loc) { - getLocalData()->TemplateKWLoc = Loc; - } - - SourceLocation getLAngleLoc() const { - return getLocalData()->LAngleLoc; - } - void setLAngleLoc(SourceLocation Loc) { - getLocalData()->LAngleLoc = Loc; - } - - SourceLocation getRAngleLoc() const { - return getLocalData()->RAngleLoc; - } - void setRAngleLoc(SourceLocation Loc) { - getLocalData()->RAngleLoc = Loc; - } - - unsigned getNumArgs() const { - return getTypePtr()->getNumArgs(); - } - void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { - getArgInfos()[i] = AI; - } - TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { - return getArgInfos()[i]; - } - - TemplateArgumentLoc getArgLoc(unsigned i) const { - return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); - } - - SourceLocation getTemplateNameLoc() const { - return getLocalData()->NameLoc; - } - void setTemplateNameLoc(SourceLocation Loc) { - getLocalData()->NameLoc = Loc; - } - - /// \brief - Copy the location information from the given info. - void copy(TemplateSpecializationTypeLoc Loc) { - unsigned size = getFullDataSize(); - assert(size == Loc.getFullDataSize()); - - // We're potentially copying Expr references here. We don't - // bother retaining them because TypeSourceInfos live forever, so - // as long as the Expr was retained when originally written into - // the TypeLoc, we're okay. - memcpy(Data, Loc.Data, size); - } - - SourceRange getLocalSourceRange() const { - if (getTemplateKeywordLoc().isValid()) - return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); - else - return SourceRange(getTemplateNameLoc(), getRAngleLoc()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setTemplateKeywordLoc(Loc); - setTemplateNameLoc(Loc); - setLAngleLoc(Loc); - setRAngleLoc(Loc); - initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), - getArgInfos(), Loc); - } - - static void initializeArgLocs(ASTContext &Context, unsigned NumArgs, - const TemplateArgument *Args, - TemplateArgumentLocInfo *ArgInfos, - SourceLocation Loc); - - unsigned getExtraLocalDataSize() const { - return getNumArgs() * sizeof(TemplateArgumentLocInfo); - } - - unsigned getExtraLocalDataAlignment() const { - return llvm::alignOf<TemplateArgumentLocInfo>(); - } - -private: - TemplateArgumentLocInfo *getArgInfos() const { - return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); - } -}; - -//===----------------------------------------------------------------------===// -// -// All of these need proper implementations. -// -//===----------------------------------------------------------------------===// - -// FIXME: size expression and attribute locations (or keyword if we -// ever fully support altivec syntax). -class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - VectorTypeLoc, - VectorType> { -}; - -// FIXME: size expression and attribute locations. -class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, - ExtVectorTypeLoc, - ExtVectorType> { -}; - -// FIXME: attribute locations. -// For some reason, this isn't a subtype of VectorType. -class DependentSizedExtVectorTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DependentSizedExtVectorTypeLoc, - DependentSizedExtVectorType> { -}; - -// FIXME: location of the '_Complex' keyword. -class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - ComplexTypeLoc, - ComplexType> { -}; - -struct TypeofLocInfo { - SourceLocation TypeofLoc; - SourceLocation LParenLoc; - SourceLocation RParenLoc; -}; - -struct TypeOfExprTypeLocInfo : public TypeofLocInfo { -}; - -struct TypeOfTypeLocInfo : public TypeofLocInfo { - TypeSourceInfo* UnderlyingTInfo; -}; - -template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> -class TypeofLikeTypeLoc - : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { -public: - SourceLocation getTypeofLoc() const { - return this->getLocalData()->TypeofLoc; - } - void setTypeofLoc(SourceLocation Loc) { - this->getLocalData()->TypeofLoc = Loc; - } - - SourceLocation getLParenLoc() const { - return this->getLocalData()->LParenLoc; - } - void setLParenLoc(SourceLocation Loc) { - this->getLocalData()->LParenLoc = Loc; - } - - SourceLocation getRParenLoc() const { - return this->getLocalData()->RParenLoc; - } - void setRParenLoc(SourceLocation Loc) { - this->getLocalData()->RParenLoc = Loc; - } - - SourceRange getParensRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); - } - void setParensRange(SourceRange range) { - setLParenLoc(range.getBegin()); - setRParenLoc(range.getEnd()); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getTypeofLoc(), getRParenLoc()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setTypeofLoc(Loc); - setLParenLoc(Loc); - setRParenLoc(Loc); - } -}; - -class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc, - TypeOfExprType, - TypeOfExprTypeLocInfo> { -public: - Expr* getUnderlyingExpr() const { - return getTypePtr()->getUnderlyingExpr(); - } - // Reimplemented to account for GNU/C++ extension - // typeof unary-expression - // where there are no parentheses. - SourceRange getLocalSourceRange() const; -}; - -class TypeOfTypeLoc - : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { -public: - QualType getUnderlyingType() const { - return this->getTypePtr()->getUnderlyingType(); - } - TypeSourceInfo* getUnderlyingTInfo() const { - return this->getLocalData()->UnderlyingTInfo; - } - void setUnderlyingTInfo(TypeSourceInfo* TI) const { - this->getLocalData()->UnderlyingTInfo = TI; - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc); -}; - -// FIXME: location of the 'decltype' and parens. -class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DecltypeTypeLoc, - DecltypeType> { -public: - Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } -}; - -struct UnaryTransformTypeLocInfo { - // FIXME: While there's only one unary transform right now, future ones may - // need different representations - SourceLocation KWLoc, LParenLoc, RParenLoc; - TypeSourceInfo *UnderlyingTInfo; -}; - -class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - UnaryTransformTypeLoc, - UnaryTransformType, - UnaryTransformTypeLocInfo> { -public: - SourceLocation getKWLoc() const { return getLocalData()->KWLoc; } - void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; } - - SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; } - void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; } - - SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } - void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } - - TypeSourceInfo* getUnderlyingTInfo() const { - return getLocalData()->UnderlyingTInfo; - } - void setUnderlyingTInfo(TypeSourceInfo *TInfo) { - getLocalData()->UnderlyingTInfo = TInfo; - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getKWLoc(), getRParenLoc()); - } - - SourceRange getParensRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); - } - void setParensRange(SourceRange Range) { - setLParenLoc(Range.getBegin()); - setRParenLoc(Range.getEnd()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKWLoc(Loc); - setRParenLoc(Loc); - setLParenLoc(Loc); - } -}; - -class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - AutoTypeLoc, - AutoType> { -}; - -struct ElaboratedLocInfo { - SourceLocation ElaboratedKWLoc; - /// \brief Data associated with the nested-name-specifier location. - void *QualifierData; -}; - -class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - ElaboratedTypeLoc, - ElaboratedType, - ElaboratedLocInfo> { -public: - SourceLocation getElaboratedKeywordLoc() const { - return this->getLocalData()->ElaboratedKWLoc; - } - void setElaboratedKeywordLoc(SourceLocation Loc) { - this->getLocalData()->ElaboratedKWLoc = Loc; - } - - NestedNameSpecifierLoc getQualifierLoc() const { - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), - getLocalData()->QualifierData); - } - - void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - assert(QualifierLoc.getNestedNameSpecifier() - == getTypePtr()->getQualifier() && - "Inconsistent nested-name-specifier pointer"); - getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); - } - - SourceRange getLocalSourceRange() const { - if (getElaboratedKeywordLoc().isValid()) - if (getQualifierLoc()) - return SourceRange(getElaboratedKeywordLoc(), - getQualifierLoc().getEndLoc()); - else - return SourceRange(getElaboratedKeywordLoc()); - else - return getQualifierLoc().getSourceRange(); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc); - - TypeLoc getNamedTypeLoc() const { - return getInnerTypeLoc(); - } - - QualType getInnerType() const { - return getTypePtr()->getNamedType(); - } - - void copy(ElaboratedTypeLoc Loc) { - unsigned size = getFullDataSize(); - assert(size == Loc.getFullDataSize()); - memcpy(Data, Loc.Data, size); - } -}; - -// This is exactly the structure of an ElaboratedTypeLoc whose inner -// type is some sort of TypeDeclTypeLoc. -struct DependentNameLocInfo : ElaboratedLocInfo { - SourceLocation NameLoc; -}; - -class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - DependentNameTypeLoc, - DependentNameType, - DependentNameLocInfo> { -public: - SourceLocation getElaboratedKeywordLoc() const { - return this->getLocalData()->ElaboratedKWLoc; - } - void setElaboratedKeywordLoc(SourceLocation Loc) { - this->getLocalData()->ElaboratedKWLoc = Loc; - } - - NestedNameSpecifierLoc getQualifierLoc() const { - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), - getLocalData()->QualifierData); - } - - void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - assert(QualifierLoc.getNestedNameSpecifier() - == getTypePtr()->getQualifier() && - "Inconsistent nested-name-specifier pointer"); - getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); - } - - SourceLocation getNameLoc() const { - return this->getLocalData()->NameLoc; - } - void setNameLoc(SourceLocation Loc) { - this->getLocalData()->NameLoc = Loc; - } - - SourceRange getLocalSourceRange() const { - if (getElaboratedKeywordLoc().isValid()) - return SourceRange(getElaboratedKeywordLoc(), getNameLoc()); - else - return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); - } - - void copy(DependentNameTypeLoc Loc) { - unsigned size = getFullDataSize(); - assert(size == Loc.getFullDataSize()); - memcpy(Data, Loc.Data, size); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc); -}; - -struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { - SourceLocation TemplateKWLoc; - SourceLocation LAngleLoc; - SourceLocation RAngleLoc; - // followed by a TemplateArgumentLocInfo[] -}; - -class DependentTemplateSpecializationTypeLoc : - public ConcreteTypeLoc<UnqualTypeLoc, - DependentTemplateSpecializationTypeLoc, - DependentTemplateSpecializationType, - DependentTemplateSpecializationLocInfo> { -public: - SourceLocation getElaboratedKeywordLoc() const { - return this->getLocalData()->ElaboratedKWLoc; - } - void setElaboratedKeywordLoc(SourceLocation Loc) { - this->getLocalData()->ElaboratedKWLoc = Loc; - } - - NestedNameSpecifierLoc getQualifierLoc() const { - if (!getLocalData()->QualifierData) - return NestedNameSpecifierLoc(); - - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), - getLocalData()->QualifierData); - } - - void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - if (!QualifierLoc) { - // Even if we have a nested-name-specifier in the dependent - // template specialization type, we won't record the nested-name-specifier - // location information when this type-source location information is - // part of a nested-name-specifier. - getLocalData()->QualifierData = nullptr; - return; - } - - assert(QualifierLoc.getNestedNameSpecifier() - == getTypePtr()->getQualifier() && - "Inconsistent nested-name-specifier pointer"); - getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); - } - - SourceLocation getTemplateKeywordLoc() const { - return getLocalData()->TemplateKWLoc; - } - void setTemplateKeywordLoc(SourceLocation Loc) { - getLocalData()->TemplateKWLoc = Loc; - } - - SourceLocation getTemplateNameLoc() const { - return this->getLocalData()->NameLoc; - } - void setTemplateNameLoc(SourceLocation Loc) { - this->getLocalData()->NameLoc = Loc; - } - - SourceLocation getLAngleLoc() const { - return this->getLocalData()->LAngleLoc; - } - void setLAngleLoc(SourceLocation Loc) { - this->getLocalData()->LAngleLoc = Loc; - } - - SourceLocation getRAngleLoc() const { - return this->getLocalData()->RAngleLoc; - } - void setRAngleLoc(SourceLocation Loc) { - this->getLocalData()->RAngleLoc = Loc; - } - - unsigned getNumArgs() const { - return getTypePtr()->getNumArgs(); - } - - void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { - getArgInfos()[i] = AI; - } - TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { - return getArgInfos()[i]; - } - - TemplateArgumentLoc getArgLoc(unsigned i) const { - return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); - } - - SourceRange getLocalSourceRange() const { - if (getElaboratedKeywordLoc().isValid()) - return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc()); - else if (getQualifierLoc()) - return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); - else if (getTemplateKeywordLoc().isValid()) - return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); - else - return SourceRange(getTemplateNameLoc(), getRAngleLoc()); - } - - void copy(DependentTemplateSpecializationTypeLoc Loc) { - unsigned size = getFullDataSize(); - assert(size == Loc.getFullDataSize()); - memcpy(Data, Loc.Data, size); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc); - - unsigned getExtraLocalDataSize() const { - return getNumArgs() * sizeof(TemplateArgumentLocInfo); - } - - unsigned getExtraLocalDataAlignment() const { - return llvm::alignOf<TemplateArgumentLocInfo>(); - } - -private: - TemplateArgumentLocInfo *getArgInfos() const { - return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); - } -}; - - -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(); - } -}; - -struct AtomicTypeLocInfo { - SourceLocation KWLoc, LParenLoc, RParenLoc; -}; - -class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc, - AtomicType, AtomicTypeLocInfo> { -public: - TypeLoc getValueLoc() const { - return this->getInnerTypeLoc(); - } - - SourceRange getLocalSourceRange() const { - return SourceRange(getKWLoc(), getRParenLoc()); - } - - SourceLocation getKWLoc() const { - return this->getLocalData()->KWLoc; - } - void setKWLoc(SourceLocation Loc) { - this->getLocalData()->KWLoc = Loc; - } - - SourceLocation getLParenLoc() const { - return this->getLocalData()->LParenLoc; - } - void setLParenLoc(SourceLocation Loc) { - this->getLocalData()->LParenLoc = Loc; - } - - SourceLocation getRParenLoc() const { - return this->getLocalData()->RParenLoc; - } - void setRParenLoc(SourceLocation Loc) { - this->getLocalData()->RParenLoc = Loc; - } - - SourceRange getParensRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); - } - void setParensRange(SourceRange Range) { - setLParenLoc(Range.getBegin()); - setRParenLoc(Range.getEnd()); - } - - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKWLoc(Loc); - setLParenLoc(Loc); - setRParenLoc(Loc); - } - - QualType getInnerType() const { - return this->getTypePtr()->getValueType(); - } -}; - - -} - -#endif diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def deleted file mode 100644 index 4590e48..0000000 --- a/include/clang/AST/TypeLocNodes.def +++ /dev/null @@ -1,41 +0,0 @@ -//===-- TypeLocNodes.def - Metadata about TypeLoc wrappers ------*- 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 TypeLoc info database. Each node is -// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc") -// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc -// are associated -// -// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is -// provided, there will be exactly one of these, Qualified. -// -// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass. -// -// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc. -// -//===----------------------------------------------------------------------===// - -#ifndef UNQUAL_TYPELOC -# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base) -#endif - -#ifndef ABSTRACT_TYPELOC -# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base) -#endif - -TYPELOC(Qualified, TypeLoc) -#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc) -#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc) -#include "clang/AST/TypeNodes.def" - -#undef DECLARATOR_TYPELOC -#undef TYPESPEC_TYPELOC -#undef ABSTRACT_TYPELOC -#undef UNQUAL_TYPELOC -#undef TYPELOC diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h deleted file mode 100644 index db5775a..0000000 --- a/include/clang/AST/TypeLocVisitor.h +++ /dev/null @@ -1,62 +0,0 @@ -//===--- TypeLocVisitor.h - Visitor for TypeLoc subclasses ------*- 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 TypeLocVisitor interface. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_TYPELOCVISITOR_H -#define LLVM_CLANG_AST_TYPELOCVISITOR_H - -#include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeVisitor.h" -#include "llvm/Support/ErrorHandling.h" - -namespace clang { - -#define DISPATCH(CLASSNAME) \ - return static_cast<ImplClass*>(this)-> \ - Visit##CLASSNAME(TyLoc.castAs<CLASSNAME>()) - -template<typename ImplClass, typename RetTy=void> -class TypeLocVisitor { -public: - RetTy Visit(TypeLoc TyLoc) { - switch (TyLoc.getTypeLocClass()) { -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); -#include "clang/AST/TypeLocNodes.def" - } - llvm_unreachable("unexpected type loc class!"); - } - - RetTy Visit(UnqualTypeLoc TyLoc) { - switch (TyLoc.getTypeLocClass()) { -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); -#include "clang/AST/TypeLocNodes.def" - } - llvm_unreachable("unexpected type loc class!"); - } - -#define TYPELOC(CLASS, PARENT) \ - RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ - DISPATCH(PARENT); \ - } -#include "clang/AST/TypeLocNodes.def" - - RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); } -}; - -#undef DISPATCH - -} // end namespace clang - -#endif // LLVM_CLANG_AST_TYPELOCVISITOR_H diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def deleted file mode 100644 index 2549f0b..0000000 --- a/include/clang/AST/TypeNodes.def +++ /dev/null @@ -1,129 +0,0 @@ -//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- 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 AST type info database. Each type node is -// enumerated by providing its name (e.g., "Builtin" or "Enum") and -// base class (e.g., "Type" or "TagType"). Depending on where in the -// abstract syntax tree the type will show up, the enumeration uses -// one of five different macros: -// -// TYPE(Class, Base) - A type that can show up anywhere in the AST, -// and might be dependent, canonical, or non-canonical. All clients -// will need to understand these types. -// -// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in -// the type hierarchy but has no concrete instances. -// -// NON_CANONICAL_TYPE(Class, Base) - A type that can show up -// anywhere in the AST but will never be a part of a canonical -// type. Clients that only need to deal with canonical types -// (ignoring, e.g., typedefs and other type alises used for -// pretty-printing) can ignore these types. -// -// DEPENDENT_TYPE(Class, Base) - A type that will only show up -// within a C++ template that has not been instantiated, e.g., a -// type that is always dependent. Clients that do not need to deal -// with uninstantiated C++ templates can ignore these types. -// -// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that -// is non-canonical unless it is dependent. Defaults to TYPE because -// it is neither reliably dependent nor reliably non-canonical. -// -// There is a sixth macro, independent of the others. Most clients -// will not need to use it. -// -// LEAF_TYPE(Class) - A type that never has inner types. Clients -// which can operate on such types more efficiently may wish to do so. -// -//===----------------------------------------------------------------------===// - -#ifndef ABSTRACT_TYPE -# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef NON_CANONICAL_TYPE -# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef DEPENDENT_TYPE -# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE -# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -TYPE(Builtin, Type) -TYPE(Complex, Type) -TYPE(Pointer, Type) -TYPE(BlockPointer, Type) -ABSTRACT_TYPE(Reference, Type) -TYPE(LValueReference, ReferenceType) -TYPE(RValueReference, ReferenceType) -TYPE(MemberPointer, Type) -ABSTRACT_TYPE(Array, Type) -TYPE(ConstantArray, ArrayType) -TYPE(IncompleteArray, ArrayType) -TYPE(VariableArray, ArrayType) -DEPENDENT_TYPE(DependentSizedArray, ArrayType) -DEPENDENT_TYPE(DependentSizedExtVector, Type) -TYPE(Vector, Type) -TYPE(ExtVector, VectorType) -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_TYPE(Adjusted, Type) -NON_CANONICAL_TYPE(Decayed, AdjustedType) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type) -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) -TYPE(Auto, Type) -DEPENDENT_TYPE(InjectedClassName, Type) -DEPENDENT_TYPE(DependentName, Type) -DEPENDENT_TYPE(DependentTemplateSpecialization, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type) -TYPE(ObjCObject, Type) -TYPE(ObjCInterface, ObjCObjectType) -TYPE(ObjCObjectPointer, Type) -TYPE(Atomic, Type) - -#ifdef LAST_TYPE -LAST_TYPE(Atomic) -#undef LAST_TYPE -#endif - -// These types are always leaves in the type hierarchy. -#ifdef LEAF_TYPE -LEAF_TYPE(Enum) -LEAF_TYPE(Builtin) -LEAF_TYPE(Record) -LEAF_TYPE(InjectedClassName) -LEAF_TYPE(ObjCInterface) -LEAF_TYPE(TemplateTypeParm) -#undef LEAF_TYPE -#endif - -#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE -#undef DEPENDENT_TYPE -#undef NON_CANONICAL_TYPE -#undef ABSTRACT_TYPE -#undef TYPE diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h deleted file mode 100644 index 392e544..0000000 --- a/include/clang/AST/TypeOrdering.h +++ /dev/null @@ -1,79 +0,0 @@ -//===-------------- TypeOrdering.h - Total ordering for types -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Allows QualTypes to be sorted and hence used in maps and sets. -/// -/// Defines clang::QualTypeOrdering, a total ordering on clang::QualType, -/// and hence enables QualType values to be sorted and to be used in -/// std::maps, std::sets, llvm::DenseMaps, and llvm::DenseSets. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TYPEORDERING_H -#define LLVM_CLANG_AST_TYPEORDERING_H - -#include "clang/AST/CanonicalType.h" -#include "clang/AST/Type.h" -#include <functional> - -namespace clang { - -/// \brief Function object that provides a total ordering on QualType values. -struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> { - bool operator()(QualType T1, QualType T2) const { - return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); - } -}; - -} - -namespace llvm { - template<class> struct DenseMapInfo; - - template<> struct DenseMapInfo<clang::QualType> { - static inline clang::QualType getEmptyKey() { return clang::QualType(); } - - static inline clang::QualType getTombstoneKey() { - using clang::QualType; - return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); - } - - static unsigned getHashValue(clang::QualType Val) { - return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ - ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); - } - - static bool isEqual(clang::QualType LHS, clang::QualType RHS) { - return LHS == RHS; - } - }; - - template<> struct DenseMapInfo<clang::CanQualType> { - static inline clang::CanQualType getEmptyKey() { - return clang::CanQualType(); - } - - static inline clang::CanQualType getTombstoneKey() { - using clang::CanQualType; - return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); - } - - static unsigned getHashValue(clang::CanQualType Val) { - return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ - ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); - } - - static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) { - return LHS == RHS; - } - }; -} - -#endif diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h deleted file mode 100644 index 11e5a47..0000000 --- a/include/clang/AST/TypeVisitor.h +++ /dev/null @@ -1,95 +0,0 @@ -//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- 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 TypeVisitor interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TYPEVISITOR_H -#define LLVM_CLANG_AST_TYPEVISITOR_H - -#include "clang/AST/Type.h" - -namespace clang { - -#define DISPATCH(CLASS) \ - return static_cast<ImplClass*>(this)-> \ - Visit##CLASS(static_cast<const CLASS*>(T)) - -/// \brief An operation on a type. -/// -/// \tparam ImplClass Class implementing the operation. Must be inherited from -/// TypeVisitor. -/// \tparam RetTy %Type of result produced by the operation. -/// -/// The class implements polymorphic operation on an object of type derived -/// from Type. The operation is performed by calling method Visit. It then -/// dispatches the call to function \c VisitFooType, if actual argument type -/// is \c FooType. -/// -/// The class implements static polymorphism using Curiously Recurring -/// Template Pattern. It is designed to be a base class for some concrete -/// class: -/// -/// \code -/// class SomeVisitor : public TypeVisitor<SomeVisitor,sometype> { ... }; -/// ... -/// Type *atype = ... -/// ... -/// SomeVisitor avisitor; -/// sometype result = avisitor.Visit(atype); -/// \endcode -/// -/// Actual treatment is made by methods of the derived class, TypeVisitor only -/// dispatches call to the appropriate method. If the implementation class -/// \c ImplClass provides specific action for some type, say -/// \c ConstantArrayType, it should define method -/// <tt>VisitConstantArrayType(const ConstantArrayType*)</tt>. Otherwise -/// \c TypeVisitor dispatches call to the method that handles parent type. In -/// this example handlers are tried in the sequence: -/// -/// \li <tt>ImplClass::VisitConstantArrayType(const ConstantArrayType*)</tt> -/// \li <tt>ImplClass::VisitArrayType(const ArrayType*)</tt> -/// \li <tt>ImplClass::VisitType(const Type*)</tt> -/// \li <tt>TypeVisitor::VisitType(const Type*)</tt> -/// -/// The first function of this sequence that is defined will handle object of -/// type \c ConstantArrayType. -template<typename ImplClass, typename RetTy=void> -class TypeVisitor { -public: - - /// \brief Performs the operation associated with this visitor object. - RetTy Visit(const Type *T) { - // Top switch stmt: dispatch to VisitFooType for each FooType. - switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type); -#include "clang/AST/TypeNodes.def" - } - llvm_unreachable("Unknown type class!"); - } - - // If the implementation chooses not to implement a certain visit method, fall - // back on superclass. -#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \ - DISPATCH(PARENT); \ -} -#include "clang/AST/TypeNodes.def" - - /// \brief Method called if \c ImpClass doesn't provide specific handler - /// for some type class. - RetTy VisitType(const Type*) { return RetTy(); } -}; - -#undef DISPATCH - -} // end namespace clang - -#endif diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h deleted file mode 100644 index 26ee1cf..0000000 --- a/include/clang/AST/UnresolvedSet.h +++ /dev/null @@ -1,140 +0,0 @@ -//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- 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 UnresolvedSet class, which is used to store -// collections of declarations in the AST. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H -#define LLVM_CLANG_AST_UNRESOLVEDSET_H - -#include "clang/AST/DeclAccessPair.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator.h" - -namespace clang { - -/// The iterator over UnresolvedSets. Serves as both the const and -/// non-const iterator. -class UnresolvedSetIterator : public llvm::iterator_adaptor_base< - UnresolvedSetIterator, DeclAccessPair *, - std::random_access_iterator_tag, NamedDecl *, - std::ptrdiff_t, NamedDecl *, NamedDecl *> { - friend class UnresolvedSetImpl; - friend class ASTUnresolvedSet; - friend class OverloadExpr; - - explicit UnresolvedSetIterator(DeclAccessPair *Iter) - : iterator_adaptor_base(Iter) {} - explicit UnresolvedSetIterator(const DeclAccessPair *Iter) - : iterator_adaptor_base(const_cast<DeclAccessPair *>(Iter)) {} - -public: - UnresolvedSetIterator() {} - - NamedDecl *getDecl() const { return I->getDecl(); } - void setDecl(NamedDecl *ND) const { return I->setDecl(ND); } - AccessSpecifier getAccess() const { return I->getAccess(); } - void setAccess(AccessSpecifier AS) { I->setAccess(AS); } - const DeclAccessPair &getPair() const { return *I; } - - NamedDecl *operator*() const { return getDecl(); } - NamedDecl *operator->() const { return **this; } -}; - -/// \brief A set of unresolved declarations. -class UnresolvedSetImpl { - typedef SmallVectorImpl<DeclAccessPair> DeclsTy; - - // Don't allow direct construction, and only permit subclassing by - // UnresolvedSet. -private: - template <unsigned N> friend class UnresolvedSet; - UnresolvedSetImpl() {} - UnresolvedSetImpl(const UnresolvedSetImpl &) {} - -public: - // We don't currently support assignment through this iterator, so we might - // as well use the same implementation twice. - typedef UnresolvedSetIterator iterator; - typedef UnresolvedSetIterator const_iterator; - - iterator begin() { return iterator(decls().begin()); } - iterator end() { return iterator(decls().end()); } - - const_iterator begin() const { return const_iterator(decls().begin()); } - const_iterator end() const { return const_iterator(decls().end()); } - - void addDecl(NamedDecl *D) { - addDecl(D, AS_none); - } - - void addDecl(NamedDecl *D, AccessSpecifier AS) { - decls().push_back(DeclAccessPair::make(D, AS)); - } - - /// Replaces the given declaration with the new one, once. - /// - /// \return true if the set changed - bool replace(const NamedDecl* Old, NamedDecl *New) { - for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I) - if (I->getDecl() == Old) - return (I->setDecl(New), true); - return false; - } - - /// Replaces the declaration at the given iterator with the new one, - /// preserving the original access bits. - void replace(iterator I, NamedDecl *New) { I.I->setDecl(New); } - - void replace(iterator I, NamedDecl *New, AccessSpecifier AS) { - I.I->set(New, AS); - } - - void erase(unsigned I) { decls()[I] = decls().pop_back_val(); } - - void erase(iterator I) { *I.I = decls().pop_back_val(); } - - void setAccess(iterator I, AccessSpecifier AS) { I.I->setAccess(AS); } - - void clear() { decls().clear(); } - void set_size(unsigned N) { decls().set_size(N); } - - bool empty() const { return decls().empty(); } - unsigned size() const { return decls().size(); } - - void append(iterator I, iterator E) { decls().append(I.I, E.I); } - - DeclAccessPair &operator[](unsigned I) { return decls()[I]; } - const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; } - -private: - // These work because the only permitted subclass is UnresolvedSetImpl - - DeclsTy &decls() { - return *reinterpret_cast<DeclsTy*>(this); - } - const DeclsTy &decls() const { - return *reinterpret_cast<const DeclsTy*>(this); - } -}; - -/// \brief A set of unresolved declarations. -template <unsigned InlineCapacity> class UnresolvedSet : - public UnresolvedSetImpl { - SmallVector<DeclAccessPair, InlineCapacity> Decls; -}; - - -} // namespace clang - -#endif diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h deleted file mode 100644 index 727bf51..0000000 --- a/include/clang/AST/VTTBuilder.h +++ /dev/null @@ -1,162 +0,0 @@ -//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with generation of the layout of virtual table -// tables (VTT). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_VTTBUILDER_H -#define LLVM_CLANG_AST_VTTBUILDER_H - -#include "clang/AST/BaseSubobject.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/ABI.h" -#include "llvm/ADT/SetVector.h" -#include <utility> - -namespace clang { - -class VTTVTable { - llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; - CharUnits BaseOffset; - -public: - VTTVTable() {} - VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) - : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} - VTTVTable(BaseSubobject Base, bool BaseIsVirtual) - : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), - BaseOffset(Base.getBaseOffset()) {} - - const CXXRecordDecl *getBase() const { - return BaseAndIsVirtual.getPointer(); - } - - CharUnits getBaseOffset() const { - return BaseOffset; - } - - bool isVirtual() const { - return BaseAndIsVirtual.getInt(); - } - - BaseSubobject getBaseSubobject() const { - return BaseSubobject(getBase(), getBaseOffset()); - } -}; - -struct VTTComponent { - uint64_t VTableIndex; - BaseSubobject VTableBase; - - VTTComponent() {} - VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) - : VTableIndex(VTableIndex), VTableBase(VTableBase) {} -}; - -/// \brief Class for building VTT layout information. -class VTTBuilder { - - ASTContext &Ctx; - - /// \brief The most derived class for which we're building this vtable. - const CXXRecordDecl *MostDerivedClass; - - typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy; - - /// \brief The VTT vtables. - VTTVTablesVectorTy VTTVTables; - - typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy; - - /// \brief The VTT components. - VTTComponentsVectorTy VTTComponents; - - /// \brief The AST record layout of the most derived class. - const ASTRecordLayout &MostDerivedClassLayout; - - typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; - - /// \brief The sub-VTT indices for the bases of the most derived class. - llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies; - - /// \brief The secondary virtual pointer indices of all subobjects of - /// the most derived class. - llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; - - /// \brief Whether the VTT builder should generate LLVM IR for the VTT. - bool GenerateDefinition; - - /// \brief Add a vtable pointer to the VTT currently being built. - void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, - const CXXRecordDecl *VTableClass); - - /// \brief Lay out the secondary VTTs of the given base subobject. - void LayoutSecondaryVTTs(BaseSubobject Base); - - /// \brief Lay out the secondary virtual pointers for the given base - /// subobject. - /// - /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base - /// or a direct or indirect base of a virtual base. - void LayoutSecondaryVirtualPointers(BaseSubobject Base, - bool BaseIsMorallyVirtual, - uint64_t VTableIndex, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases); - - /// \brief Lay out the secondary virtual pointers for the given base - /// subobject. - void LayoutSecondaryVirtualPointers(BaseSubobject Base, - uint64_t VTableIndex); - - /// \brief Lay out the VTTs for the virtual base classes of the given - /// record declaration. - void LayoutVirtualVTTs(const CXXRecordDecl *RD, - VisitedVirtualBasesSetTy &VBases); - - /// \brief Lay out the VTT for the given subobject, including any - /// secondary VTTs, secondary virtual pointers and virtual VTTs. - void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); - -public: - VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition); - - // \brief Returns a reference to the VTT components. - const VTTComponentsVectorTy &getVTTComponents() const { - return VTTComponents; - } - - // \brief Returns a reference to the VTT vtables. - const VTTVTablesVectorTy &getVTTVTables() const { - return VTTVTables; - } - - /// \brief Returns a reference to the sub-VTT indices. - const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const { - return SubVTTIndicies; - } - - /// \brief Returns a reference to the secondary virtual pointer indices. - const llvm::DenseMap<BaseSubobject, uint64_t> & - getSecondaryVirtualPointerIndices() const { - return SecondaryVirtualPointerIndices; - } - -}; - -} - -#endif diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h deleted file mode 100644 index 481fd11..0000000 --- a/include/clang/AST/VTableBuilder.h +++ /dev/null @@ -1,566 +0,0 @@ -//===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with generation of the layout of virtual tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_VTABLEBUILDER_H -#define LLVM_CLANG_AST_VTABLEBUILDER_H - -#include "clang/AST/BaseSubobject.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/ABI.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SetVector.h" -#include <memory> -#include <utility> - -namespace clang { - class CXXRecordDecl; - -/// \brief Represents a single component in a vtable. -class VTableComponent { -public: - enum Kind { - CK_VCallOffset, - CK_VBaseOffset, - CK_OffsetToTop, - CK_RTTI, - CK_FunctionPointer, - - /// \brief A pointer to the complete destructor. - CK_CompleteDtorPointer, - - /// \brief A pointer to the deleting destructor. - CK_DeletingDtorPointer, - - /// \brief An entry that is never used. - /// - /// In some cases, a vtable function pointer will end up never being - /// called. Such vtable function pointers are represented as a - /// CK_UnusedFunctionPointer. - CK_UnusedFunctionPointer - }; - - VTableComponent() = default; - - static VTableComponent MakeVCallOffset(CharUnits Offset) { - return VTableComponent(CK_VCallOffset, Offset); - } - - static VTableComponent MakeVBaseOffset(CharUnits Offset) { - return VTableComponent(CK_VBaseOffset, Offset); - } - - static VTableComponent MakeOffsetToTop(CharUnits Offset) { - return VTableComponent(CK_OffsetToTop, Offset); - } - - static VTableComponent MakeRTTI(const CXXRecordDecl *RD) { - return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD)); - } - - static VTableComponent MakeFunction(const CXXMethodDecl *MD) { - assert(!isa<CXXDestructorDecl>(MD) && - "Don't use MakeFunction with destructors!"); - - return VTableComponent(CK_FunctionPointer, - reinterpret_cast<uintptr_t>(MD)); - } - - static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) { - return VTableComponent(CK_CompleteDtorPointer, - reinterpret_cast<uintptr_t>(DD)); - } - - static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) { - return VTableComponent(CK_DeletingDtorPointer, - reinterpret_cast<uintptr_t>(DD)); - } - - static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) { - assert(!isa<CXXDestructorDecl>(MD) && - "Don't use MakeUnusedFunction with destructors!"); - return VTableComponent(CK_UnusedFunctionPointer, - reinterpret_cast<uintptr_t>(MD)); - } - - static VTableComponent getFromOpaqueInteger(uint64_t I) { - return VTableComponent(I); - } - - /// \brief Get the kind of this vtable component. - Kind getKind() const { - return (Kind)(Value & 0x7); - } - - CharUnits getVCallOffset() const { - assert(getKind() == CK_VCallOffset && "Invalid component kind!"); - - return getOffset(); - } - - CharUnits getVBaseOffset() const { - assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); - - return getOffset(); - } - - CharUnits getOffsetToTop() const { - assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); - - return getOffset(); - } - - const CXXRecordDecl *getRTTIDecl() const { - assert(isRTTIKind() && "Invalid component kind!"); - return reinterpret_cast<CXXRecordDecl *>(getPointer()); - } - - const CXXMethodDecl *getFunctionDecl() const { - assert(isFunctionPointerKind() && "Invalid component kind!"); - if (isDestructorKind()) - return getDestructorDecl(); - return reinterpret_cast<CXXMethodDecl *>(getPointer()); - } - - const CXXDestructorDecl *getDestructorDecl() const { - assert(isDestructorKind() && "Invalid component kind!"); - return reinterpret_cast<CXXDestructorDecl *>(getPointer()); - } - - const CXXMethodDecl *getUnusedFunctionDecl() const { - assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!"); - return reinterpret_cast<CXXMethodDecl *>(getPointer()); - } - - bool isDestructorKind() const { return isDestructorKind(getKind()); } - - bool isUsedFunctionPointerKind() const { - return isUsedFunctionPointerKind(getKind()); - } - - bool isFunctionPointerKind() const { - return isFunctionPointerKind(getKind()); - } - - bool isRTTIKind() const { return isRTTIKind(getKind()); } - -private: - static bool isFunctionPointerKind(Kind ComponentKind) { - return isUsedFunctionPointerKind(ComponentKind) || - ComponentKind == CK_UnusedFunctionPointer; - } - static bool isUsedFunctionPointerKind(Kind ComponentKind) { - return ComponentKind == CK_FunctionPointer || - isDestructorKind(ComponentKind); - } - static bool isDestructorKind(Kind ComponentKind) { - return ComponentKind == CK_CompleteDtorPointer || - ComponentKind == CK_DeletingDtorPointer; - } - static bool isRTTIKind(Kind ComponentKind) { - return ComponentKind == CK_RTTI; - } - - VTableComponent(Kind ComponentKind, CharUnits Offset) { - assert((ComponentKind == CK_VCallOffset || - ComponentKind == CK_VBaseOffset || - ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); - assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!"); - assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!"); - - Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind; - } - - VTableComponent(Kind ComponentKind, uintptr_t Ptr) { - assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) && - "Invalid component kind!"); - - assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); - - Value = Ptr | ComponentKind; - } - - CharUnits getOffset() const { - assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || - getKind() == CK_OffsetToTop) && "Invalid component kind!"); - - return CharUnits::fromQuantity(Value >> 3); - } - - uintptr_t getPointer() const { - assert((getKind() == CK_RTTI || isFunctionPointerKind()) && - "Invalid component kind!"); - - return static_cast<uintptr_t>(Value & ~7ULL); - } - - explicit VTableComponent(uint64_t Value) - : Value(Value) { } - - /// The kind is stored in the lower 3 bits of the value. For offsets, we - /// make use of the facts that classes can't be larger than 2^55 bytes, - /// so we store the offset in the lower part of the 61 bits that remain. - /// (The reason that we're not simply using a PointerIntPair here is that we - /// need the offsets to be 64-bit, even when on a 32-bit machine). - int64_t Value; -}; - -class VTableLayout { -public: - typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy; - - typedef const VTableComponent *vtable_component_iterator; - typedef const VTableThunkTy *vtable_thunk_iterator; - typedef llvm::iterator_range<vtable_component_iterator> - vtable_component_range; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; - -private: - uint64_t NumVTableComponents; - std::unique_ptr<VTableComponent[]> VTableComponents; - - /// \brief Contains thunks needed by vtables, sorted by indices. - uint64_t NumVTableThunks; - std::unique_ptr<VTableThunkTy[]> VTableThunks; - - /// \brief Address points for all vtables. - AddressPointsMapTy AddressPoints; - - bool IsMicrosoftABI; - -public: - VTableLayout(uint64_t NumVTableComponents, - const VTableComponent *VTableComponents, - uint64_t NumVTableThunks, - const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints, - bool IsMicrosoftABI); - ~VTableLayout(); - - uint64_t getNumVTableComponents() const { - return NumVTableComponents; - } - - vtable_component_range vtable_components() const { - return vtable_component_range(vtable_component_begin(), - vtable_component_end()); - } - - vtable_component_iterator vtable_component_begin() const { - return VTableComponents.get(); - } - - vtable_component_iterator vtable_component_end() const { - return VTableComponents.get() + NumVTableComponents; - } - - uint64_t getNumVTableThunks() const { return NumVTableThunks; } - - vtable_thunk_iterator vtable_thunk_begin() const { - return VTableThunks.get(); - } - - vtable_thunk_iterator vtable_thunk_end() const { - return VTableThunks.get() + NumVTableThunks; - } - - uint64_t getAddressPoint(BaseSubobject Base) const { - assert(AddressPoints.count(Base) && - "Did not find address point!"); - - uint64_t AddressPoint = AddressPoints.lookup(Base); - assert(AddressPoint != 0 || IsMicrosoftABI); - (void)IsMicrosoftABI; - - return AddressPoint; - } - - const AddressPointsMapTy &getAddressPoints() const { - return AddressPoints; - } -}; - -class VTableContextBase { -public: - typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; - - bool isMicrosoft() const { return IsMicrosoftABI; } - - virtual ~VTableContextBase() {} - -protected: - typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; - - /// \brief Contains all thunks that a given method decl will need. - ThunksMapTy Thunks; - - /// Compute and store all vtable related information (vtable layout, vbase - /// offset offsets, thunks etc) for the given record decl. - virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0; - - VTableContextBase(bool MS) : IsMicrosoftABI(MS) {} - -public: - virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl()); - computeVTableRelatedInformation(MD->getParent()); - - // This assumes that all the destructors present in the vtable - // use exactly the same set of thunks. - ThunksMapTy::const_iterator I = Thunks.find(MD); - if (I == Thunks.end()) { - // We did not find a thunk for this method. - return nullptr; - } - - return &I->second; - } - - bool IsMicrosoftABI; -}; - -class ItaniumVTableContext : public VTableContextBase { -private: - - /// \brief Contains the index (relative to the vtable address point) - /// where the function pointer for a virtual function is stored. - typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; - MethodVTableIndicesTy MethodVTableIndices; - - typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *> - VTableLayoutMapTy; - VTableLayoutMapTy VTableLayouts; - - typedef std::pair<const CXXRecordDecl *, - const CXXRecordDecl *> ClassPairTy; - - /// \brief vtable offsets for offsets of virtual bases of a class. - /// - /// Contains the vtable offset (relative to the address point) in chars - /// where the offsets for virtual bases of a class are stored. - typedef llvm::DenseMap<ClassPairTy, CharUnits> - VirtualBaseClassOffsetOffsetsMapTy; - VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; - - void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; - -public: - ItaniumVTableContext(ASTContext &Context); - ~ItaniumVTableContext() override; - - const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { - computeVTableRelatedInformation(RD); - assert(VTableLayouts.count(RD) && "No layout for this record decl!"); - - return *VTableLayouts[RD]; - } - - VTableLayout * - createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, - CharUnits MostDerivedClassOffset, - bool MostDerivedClassIsVirtual, - const CXXRecordDecl *LayoutClass); - - /// \brief Locate a virtual function in the vtable. - /// - /// Return the index (relative to the vtable address point) where the - /// function pointer for the given virtual function is stored. - uint64_t getMethodVTableIndex(GlobalDecl GD); - - /// Return the offset in chars (relative to the vtable address point) where - /// the offset of the virtual base that contains the given base is stored, - /// otherwise, if no virtual base contains the given class, return 0. - /// - /// Base must be a virtual base class or an unambiguous base. - CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, - const CXXRecordDecl *VBase); - - static bool classof(const VTableContextBase *VT) { - return !VT->isMicrosoft(); - } -}; - -/// Holds information about the inheritance path to a virtual base or function -/// table pointer. A record may contain as many vfptrs or vbptrs as there are -/// base subobjects. -struct VPtrInfo { - typedef SmallVector<const CXXRecordDecl *, 1> BasePath; - - VPtrInfo(const CXXRecordDecl *RD) - : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {} - - /// The vtable will hold all of the virtual bases or virtual methods of - /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base. - /// A derived class will reuse the vptr of the first non-virtual base - /// subobject that has one. - const CXXRecordDecl *ReusingBase; - - /// BaseWithVPtr is at this offset from its containing complete object or - /// virtual base. - CharUnits NonVirtualOffset; - - /// The vptr is stored inside this subobject. - const CXXRecordDecl *BaseWithVPtr; - - /// The bases from the inheritance path that got used to mangle the vbtable - /// name. This is not really a full path like a CXXBasePath. It holds the - /// subset of records that need to be mangled into the vbtable symbol name in - /// order to get a unique name. - BasePath MangledPath; - - /// The next base to push onto the mangled path if this path is ambiguous in a - /// derived class. If it's null, then it's already been pushed onto the path. - const CXXRecordDecl *NextBaseToMangle; - - /// The set of possibly indirect vbases that contain this vbtable. When a - /// derived class indirectly inherits from the same vbase twice, we only keep - /// vtables and their paths from the first instance. - BasePath ContainingVBases; - - /// This holds the base classes path from the complete type to the first base - /// with the given vfptr offset, in the base-to-derived order. Only used for - /// vftables. - BasePath PathToBaseWithVPtr; - - /// Static offset from the top of the most derived class to this vfptr, - /// including any virtual base offset. Only used for vftables. - CharUnits FullOffsetInMDC; - - /// The vptr is stored inside the non-virtual component of this virtual base. - const CXXRecordDecl *getVBaseWithVPtr() const { - return ContainingVBases.empty() ? nullptr : ContainingVBases.front(); - } -}; - -typedef SmallVector<VPtrInfo *, 2> VPtrInfoVector; - -/// All virtual base related information about a given record decl. Includes -/// information on all virtual base tables and the path components that are used -/// to mangle them. -struct VirtualBaseInfo { - ~VirtualBaseInfo() { llvm::DeleteContainerPointers(VBPtrPaths); } - - /// A map from virtual base to vbtable index for doing a conversion from the - /// the derived class to the a base. - llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices; - - /// Information on all virtual base tables used when this record is the most - /// derived class. - VPtrInfoVector VBPtrPaths; -}; - -class MicrosoftVTableContext : public VTableContextBase { -public: - struct MethodVFTableLocation { - /// If nonzero, holds the vbtable index of the virtual base with the vfptr. - uint64_t VBTableIndex; - - /// If nonnull, holds the last vbase which contains the vfptr that the - /// method definition is adjusted to. - const CXXRecordDecl *VBase; - - /// This is the offset of the vfptr from the start of the last vbase, or the - /// complete type if there are no virtual bases. - CharUnits VFPtrOffset; - - /// Method's index in the vftable. - uint64_t Index; - - MethodVFTableLocation() - : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), - Index(0) {} - - MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, - CharUnits VFPtrOffset, uint64_t Index) - : VBTableIndex(VBTableIndex), VBase(VBase), - VFPtrOffset(VFPtrOffset), Index(Index) {} - - bool operator<(const MethodVFTableLocation &other) const { - if (VBTableIndex != other.VBTableIndex) { - assert(VBase != other.VBase); - return VBTableIndex < other.VBTableIndex; - } - return std::tie(VFPtrOffset, Index) < - std::tie(other.VFPtrOffset, other.Index); - } - }; - -private: - ASTContext &Context; - - typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation> - MethodVFTableLocationsTy; - MethodVFTableLocationsTy MethodVFTableLocations; - - typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *> - VFPtrLocationsMapTy; - VFPtrLocationsMapTy VFPtrLocations; - - typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; - typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy; - VFTableLayoutMapTy VFTableLayouts; - - llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo; - - void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); - - void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; - - void dumpMethodLocations(const CXXRecordDecl *RD, - const MethodVFTableLocationsTy &NewMethods, - raw_ostream &); - - const VirtualBaseInfo * - computeVBTableRelatedInformation(const CXXRecordDecl *RD); - - void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD, - VPtrInfoVector &Paths); - -public: - MicrosoftVTableContext(ASTContext &Context) - : VTableContextBase(/*MS=*/true), Context(Context) {} - - ~MicrosoftVTableContext() override; - - const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD); - - const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, - CharUnits VFPtrOffset); - - const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); - - const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override { - // Complete destructors don't have a slot in a vftable, so no thunks needed. - if (isa<CXXDestructorDecl>(GD.getDecl()) && - GD.getDtorType() == Dtor_Complete) - return nullptr; - return VTableContextBase::getThunkInfo(GD); - } - - /// \brief Returns the index of VBase in the vbtable of Derived. - /// VBase must be a morally virtual base of Derived. - /// The vbtable is an array of i32 offsets. The first entry is a self entry, - /// and the rest are offsets from the vbptr to virtual bases. - unsigned getVBTableIndex(const CXXRecordDecl *Derived, - const CXXRecordDecl *VBase); - - const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD); - - static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); } -}; - -} // namespace clang - -#endif |